当你学习 Python 时,可能会遇到一些令人困惑的概念或语法。但是,了解一些新的、有趣的 Python 技巧可以让你更加深入地理解这门语言。在这篇文章中,我们将探讨 30 个新奇的 Python 小知识,涉及各种主题,包括函数、类、数据类型、内置函数等等。阅读本文,相信你将收获新的知识和技能,让你的 Python 之旅更加有趣和富有成效。
1、映射代理(不可变字典)
映射代理是一种字典,创建后无法更改。我们使用它的原因是不希望用户能够更改我们的值。
from types import MappingProxyType
mp = MappingProxyType({'apple':4, 'orange':5})
print(mp)
# {'apple': 4, 'orange': 5}
如果我们试图更改映射代理中的内容,就会出现错误。
from types import MappingProxyType
mp = MappingProxyType({'apple':4, 'orange':5})
print(mp)
'''
Traceback (most recent call last):
File "some/path/a.py", line 4, in <module>
mp['apple'] = 10
~~^^^^^^^^^
TypeError: 'mappingproxy' object does not support item assignment
'''
2、类和对象的 dict 不同
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
rocky = Dog('rocky', 5)
print(type(rocky.__dict__)) # <class 'dict'>
print(rocky.__dict__) # {'name': 'rocky', 'age': 5}
print(type(Dog.__dict__)) # <class 'mappingproxy'>
print(Dog.__dict__)
# {'__module__': '__main__',
# '__init__': <function Dog.__init__ at 0x108f587c0>,
# '__dict__': <attribute '__dict__' of 'Dog' objects>,
# '__weakref__': <attribute '__weakref__' of 'Dog' objects>,
# '__doc__': None}
对象的 dict 属性是普通字典,而类的 dict 属性是映射代理,本质上是不可变字典(无法更改)。
3、any() and all()
any([True, False, False]) # True
any([False, False, False]) # False
all([True, False, False]) # False
all([True, True, True]) # True
any() 和 all() 函数都接受可迭代对象(例如,列表)作为参数。
any() 函数返回 True,如果至少有一个元素为 True。 all() 函数只有在所有元素都为 True 时才返回 True。
4、divmod()
内置的 divmod() 函数可以同时执行 // 和 % 运算符。
quotient, remainder = divmod(27, 10)
print(quotient) # 2
print(remainder) # 7
在 divmod(27, 10) 中,27 // 10 的结果为 2,27 % 10 的结果为 7。因此,该函数返回元组 (2, 7)。
5、使用格式化字符串轻松查看变量
name = 'rocky'
age = 5
string = f'{name=} {age=}'
print(string)
# name='rocky' age=5
在格式化字符串中,我们可以在变量后添加 =,以使用 var_name=var_value 的语法打印它。
6、我们可以将浮点数转换为比率(有时是奇怪的)。
print(float.as_integer_ratio(0.5)) # (1, 2)
print(float.as_integer_ratio(0.25)) # (1, 4)
print(float.as_integer_ratio(1.5)) # (3, 2)
内置的 float.as_integer_ratio() 函数允许我们将浮点数转换为表示分数的元组。但有时它的行为可能有些奇怪。
print(float.as_integer_ratio(0.1)) # (3602879701896397, 36028797018963968)
print(float.as_integer_ratio(0.2)) # (3602879701896397, 18014398509481984)
7、使用 globals() 和 locals() 函数显示全局和局部变量
x = 1
print(globals())
# {'__name__': '__main__', '__doc__': None, ..., 'x': 1}
内置的 globals() 函数返回一个包含所有全局变量及其值的字典。
def test():
x = 1
y = 2
print(locals())
test()
# {'x': 1, 'y': 2}
内置的 locals() 函数返回一个包含所有局部变量及其值的字典。
8、import() 函数
import numpy as np
import pandas as pd
import() 函数是导入模块的一种常规方法。
np = __import__('numpy')
pd = __import__('pandas')
这个函数与上面的代码块执行的是完全相同的操作。
9、Python 中的无限大数值
a = float('inf')
b = float('-inf')
在 Python 中,我们可以定义正无穷和负无穷。正无穷大于所有其他数,而负无穷小于所有其他数。
10、我们可以使用 'pprint' 漂亮地打印内容
from pprint import pprint
d = {"A":{"apple":1, "orange":2, "pear":3},
"B":{"apple":4, "orange":5, "pear":6},
"C":{"apple":7, "orange":8, "pear":9}}
pprint(d)
11、我们可以在 Python 中打印带颜色的输出。
我们需要首先安装 colorama 包。
from colorama import Fore
print(Fore.RED + "hello world")
print(Fore.BLUE + "hello world")
print(Fore.GREEN + "hello world")
12、创建字典的更快方法
d1 = {'apple':'pie', 'orange':'juice', 'pear':'cake'}
通常的创建字典的方式
d2 = dict(apple='pie', orange='juice', pear='cake')
一个更快的创建字典的方式。它与上面的代码块执行的是完全相同的操作,但我们只需要输入更少的引号。
13、我们可以在 Python 中取消打印输出的内容
CURSOR_UP = '\033[1A'
CLEAR = '\x1b[2K'
print('apple')
print('orange')
print('pear')
print((CURSOR_UP + CLEAR)*2, end='') # this unprints 2 lines
print('pineapple')
打印输出的内容:
- 打印 '\033[1A' 字符会将我们的光标向上移动一行。
- 打印 '\x1b[2K' 字符会清除整个当前行。
- 当它们一起打印时,我们可以取消打印整行的内容。
14、对象中的私有变量并不是真正的私有
class Dog:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
在这里,self.__name 变量应该是私有的。我们不应该能够从类的外部访问它。但是实际上我们是可以访问的。
rocky = Dog('rocky')
print(rocky.__dict__) # {'_Dog__name': 'rocky'}
我们可以使用 dict 属性来访问或编辑这些属性。
15、我们可以使用 'type()' 创建类
classname = type(name, bases, dict)
- name 是表示类名称的字符串
- bases 是一个包含父类的元组
- dict 是一个包含属性和方法的字典
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
print(f'Dog({self.name}, {self.age})')
普通方式创建一个 Dog 类
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
print(f'Dog({self.name}, {self.age})')
Dog = type('Dog', (), {'__init__':__init__, 'bark':bark})
使用 type() 创建与上述相同的 Dog 类
16、我们可以使用中文字符作为变量
我们可以使用中文字符作为变量,也可以使用表情符号,以及几乎任何 Unicode 字符。
我 = 4
你 = 5
print(我 + 你) # 9
17、Python 中的退格符
退格符 \b 可以删除一个打印的字符。
print('abc' + '\b' + 'd') # abd
18、响铃符号允许我们发出铃声
print('\a')
可以在命令行窗口中尝试这个。打印响铃符号 '\a' 应该会发出铃声。
19、我们可以使用类作为装饰器
class add():
def __init__(self, char):
self.char = char
def __call__(self, function):
def inner(*args):
return function(*args) + self.char
return inner
@add("!")
def greet(name):
return "hello " + name
print(greet("tom")) # hello tom!
这是由 call 魔法方法实现的,它定义了当我们调用 add 对象时发生的操作。
20、函数可以拥有变量
def test():
print('test')
test.apple = 4
print(test.apple) # 4
21、对齐字符串的简单方法
可以使用字符串方法 ljust、rjust 和 center 分别将字符串填充空格并将字符串向左/右/中心对齐。
print('>' + 'hello'.ljust(10) + '<') # >hello <
print('>' + 'hello'.rjust(10) + '<') # > hello<
print('>' + 'hello'.center(10) + '<') # > hello <
或者我们可以使用格式化字符串来实现:
print(f'>{"hello":<10}<') # >hello <
print(f'>{"hello":>10}<') # > hello<
print(f'>{"hello":^10}<') # > hello <
22、当我们将一个列表加上它本身时会发生什么
lis = ['apple', 'orange']
lis.append(lis)
print(lis)
# ['apple', 'orange', [...]]
23、我们可以使用 eval() 在字符串中运行 Python 代码
print(eval('4+5')) # 9
print(eval('7-3')) # 4
eval() 是内置函数,我们不需要导入它。
24、round() 函数可以接受负数小数位数
print(round(3.14159265, 2)) # 3.14
使用 round() 的通常方法。在这里,我们将 3.14159265 四舍五入到小数点后 2 位,因此得到 3.14。
print(round(12345, -1)) # 12340
print(round(12345, -2)) # 12300
print(round(12345, -3)) # 12000
我们还可以使用 round() 函数将数字四舍五入到最接近的 10、100、1000 等整数。
25、Python 中的海象运算符 :=
n = 5
if n > 3:
print('n is more than 3')
一个简单的 for 循环
if (n := 5) > 3:
print('n is more than 3')
使用海象运算符 := 执行与上面相同的操作
在这里,海象运算符与我们的赋值运算符 = 做的事情相同。但是,它还有一个额外的功能——它还返回该值本身。因此,我们可以使用这个运算符来节省一行代码。
注意——这个功能适用于 Python 3.8+
26、我们可以将多个对象 pickling 到同一个文件中
内置的 pickle 模块允许我们将 Python 数据结构或对象保存到二进制文件中。我们可以将多个对象保存在同一个文件中。
a = [1,2,3]
b = [4,5,6]
c = [7,8,9]
import pickle
with open('test.pckl', 'wb') as f:
pickle.dump(a, f) # saving a into test.pckl (a is the 1st object)
pickle.dump(b, f) # saving b into test.pckl (b is the 2nd object)
pickle.dump(c, f) # saving c into test.pckl (c is the 3rd object)
# Unpickling (reading) them from test.pckl
import pickle
with open('test.pckl', 'rb') as f:
a = pickle.load(f) # a = [1,2,3]
b = pickle.load(f) # b = [4,5,6]
c = pickle.load(f) # c = [7,8,9]
27、-O 标志可以忽略 assert 语句
# this is run.py
assert 1==2
print('hello')
如果我们正常运行这段代码,将会收到一个 AssertionError 错误。这是因为我们尝试断言 1==2,而这个表达式的结果为 False。
我们可以通过添加 -O 标志来强制忽略所有 assert 语句。
python -O run.py
28、使用 dict.fromkeys() 创建字典
fruits = ['apple', 'orange', 'pear']
d = dict.fromkeys(fruits)
# d = {'apple':None, 'orange':None, 'pear':None}
我们可以使用 dict.fromkeys() 快速从列表创建字典。请注意,所有的值都将为 None。如果我们想要定义默认值,可以将另一个参数传递到 dict.fromkeys() 函数中。
fruits = ['apple', 'orange', 'pear']
d = dict.fromkeys(fruits, 100)
# d = {'apple':100, 'orange':100, 'pear':100}
29、冻结集合(frozensets)
冻结集合本质上是不可变的集合——在创建后无法进行任何更改的集合。
fs = frozenset({1, 2, 3})
为什么我们要使用冻结集合:
- 我们可以将冻结集合添加到其他集合中(使用集合无法做到这一点)
- 我们可以使用冻结集合作为字典键(使用集合无法做到这一点)
- 检查某个元素是否存在于冻结集合中仍然只需要 O(1) 的时间
30、我们可以使用 slots 强制类仅接受特定的属性
class Dog:
__slots__ = ['name', 'age']
本质上,这是定义了 Dog 类仅能接受 name 和 age 属性,而不能接受任何其他属性。
dog = Dog()
dog.name = 'rocky' # no problem
dog.age = 5 # no problem
dog.breed = "german shepherd" # ERROR
我们可以为 Dog 设置 name 和 age 属性,但不能设置其他属性。
结论
希望您在阅读本文后至少学到了一件有关 Python 的新知识。我们下次再见,这个列表还会变得更长。
无论是初学者还是有经验的 Python 开发者,学习新的技巧和知识都是必要的。希望在这篇文章中,我们介绍的这些 Python 技巧能够帮助你更加深入地了解 Python,提高你的编程技能,让你的代码更加简洁和高效。Python 语言的灵活性和易用性是它如此受欢迎的原因之一。希望你能够不断探索和学习 Python,创造出令人惊叹的项目和应用。
在文章结尾,我想提醒您,文章的创作不易,如果您喜欢我的分享,请别忘了点赞和转发,让更多有需要的人看到。同时,如果您想获取更多前端技术的知识,欢迎关注我,您的支持将是我分享最大的动力。我会持续输出更多内容,敬请期待。
原文:
https://python.plainenglish.io/30-things-i-never-knew-about-python-until-recently-compilation-101b0817eeca作者:Liu Zuo Lin
非直接翻译,有自行改编和添加部分,翻译水平有限,难免有疏漏,欢迎指正