Hello,大家好,我是Alex,欢迎来到每周博客!
这篇博客来给大家介绍一下Python 3.10的新特性。
Python 3.10版本带来了一些很棒的新功能和改进。
结构模式匹配
结构模式匹配可以让我们将变量与一组不同的可能值进行匹配,就类似于其它编程语言中的switch case语句,相应的Python 3.10中为match case语句。
一个简单的示例:
import random
def http_error(status) -> str:
match status:
case 400:
return "Bad Request"
case 401 | 403: # 可以将多个可能值组合在一个case
return "Not Allowed"
case 404:
return "Not Found"
case _:
return "Something's wrong with the internet"
if __name__ == '__main__':
s = random.choice([400, 401, 403, 404, 500])
print(s, http_error(s))
s = random.choice([400, 401, 403, 404, 500])
print(s, http_error(s))
输出:
D:\Python\Python310\python.exe E:/Code/PythonProject/Python310NewFeatures/main.py
403 Not Allowed
500 Something's wrong with the internet
Process finished with exit code 0
Python 3.10不仅支持与简单值进行匹配,还可以与其它数据类型进行匹配,比如元组或者设置为特定值的特定属性的类对象。
point = (3, 4)
match point:
case (0, 0):
print("Origin")
case (0, y):
print(f"x = 0, y = {y}")
case (x, 0):
print(f"x = {x}, y = 0")
case (x, y):
print(f"x = {x}, y = {y}")
case _:
raise ValueError("Not a Point")
输出:
D:\Python\Python310\python.exe E:/Code/PythonProject/Python310NewFeatures/main.py
x = 3, y = 4
Process finished with exit code 0
我们可以看到match case在许多不同的场景中都可以使用。
带括号的上下文管理器
现在已支持使用外层圆括号来使多个上下文管理器可以连续多行地书写。 这允许将过长的上下文管理器集能够以与之前 import 语句类似的方式格式化为多行的形式。 例如,以下这些示例写法现在都是有效的:
with (CtxManager() as example):
...
with (
CtxManager1(), # 在被包含的分组末尾过可以使用一个逗号作为结束:
CtxManager2()
):
...
with (CtxManager1() as example,
CtxManager2()):
...
with (CtxManager1(),
CtxManager2() as example):
...
with (
CtxManager1() as example1,
CtxManager2() as example2
):
...
zip函数的strict参数
现在 zip() 函数有一个可选的 strict 布尔参数,用于要求所有可迭代对象的长度都相等。
zip() 函数创建一个迭代器聚合来自多个可迭代项的元素,默认是当到达较短的可迭代对象的末尾时停止。
names = ["Max", "Mary", "Ben"]
ages = [22, 26]
result = zip(names, ages)
print(list(result))
输出:
[('Max', 22), ('Mary', 26)]
它只是组合了前两个元素,丢弃了第三个name。
如果设置strict参数为True,那么可迭代对象长度不等时将引发报错。
>>> names = ["Max", "Mary", "Ben"]
>>> ages = [22, 26]
>>>
>>> result = zip(names, ages, strict=True)
>>> print(list(result))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: zip() argument 2 is shorter than argument 1
更清楚的错误消息
这是我发现的非常有用的另一项改进,许多错误消息已经得到了改进,不仅提供有关错误的更精确消息,而且还提供有关错误实际发生位置的更精确信息。
例如在此代码中缺少括号,旧错误只是一条invalid syntax
,甚至连行号都不对。
Python 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Hello"
... print("World")
File "<stdin>", line 2
print("World")
^
SyntaxError: invalid syntax
而在Python 3.10中我们可以看到它正确的报错行号和错误描述。
Python 3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> Print("Hello"
... Print("World")
File "<stdin>", line 1
Print("Hello"
^^^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?
还有缩进错误的例子,我们也可以看到错误确切的行和位置以及准确的错误信息。
>>> def foo():
... if lel:
... x = 2
File "<stdin>", line 3
x = 2
^
IndentationError: expected an indented block after 'if' statement in line 2
我非常喜欢这个改进,这对初学者特别有帮助。
更新和弃用
- Python 3.10现在需要OpenSSL 1.1.1 or newer,这会影响
hashlib
、hmac
和ssl
模块的运行。 distutils
包已被废弃,将在 Python 3.12 中移除。其用指定包构建程序的功能已被第三方软件包 setuptools 和 packaging 完全取代。
优化
- 现在,构造函数 str() 、 bytes() 和 bytearray() 速度更快了(小对象大约提速 30-40%)。
- runpy 导入的模块变少了。python3 -m module-name 命令的启动时间平均加快 1.4 倍。在 Linux 上,Python 3.9 的 python3 -I -m module-name 导入了69个模块,而 Python 3.10 只导入了 51个模块(少了 18 个)。
- 当用 --enable-optimizations 构建 Python 时,会在编译和链接命令行中添加 -fno-semantic-interposition。 这会让用带参数 --enable-shared 的 gcc 构建 Python 解释器时提速 30%。
- 子串搜索函数,如 str1 in str2 和 str2.find(str1) ,有时会采用Crochemore & Perrin的“二路归并”字符串搜索算法,以避免长字符串的二次检索行为。
总结
Python 3.10带来了很多很棒的功能改进和性能优化,我觉得最有趣的就是模式匹配功能,最有用的就是更清楚的错误消息,详细的Python 3.10 有什么新变化可以参考官方文档。