全文3000字,预计阅读时间20min,建议先赞后看!
一.上下文管理器
python3.10 中,with 支持使用外层圆括号来使用多个上下文管理器,可以连续多行地书写。这允许将过长的上下文管理器集能够以与之前 import 语句类似的方式格式化为多行的形式。例如,以下这些示例写法现在都是有效的:
with (CtxManager() as example):
pass
with (
CtxManager1(),
CtxManager2()
):
pass
with (CtxManager1() as example,
CtxManager2()):
pass
with (CtxManager1(),
CtxManager2() as example):
pass
with (
CtxManager1() as example1,
CtxManager2() as example2
):
pass
二.新增结构化模式匹配
python3.10 中新增的结构化模式匹配,主要由 match、case 两个关键字实现,模式匹配的通用语法如下
status = 404
match status:
case 400:
res = "Bad request"
case 404:
res = "Not found"
case 418:
res = "I'm a teapot"
case _:
res = "Something's wrong with the internet"
match 语句接受一个表达式并将其值与以一个或多个 case 语句块形式给出的一系列模式进行比较。具体来说,模式匹配的操作如下:
使用具有特定类型和形状的数据 (subject) 针对 subject 在 match 语句中求值 从上到下对 subject 与 case 语句中的每个模式进行比较直到确认匹配到一个模式。 执行与被确认匹配的模式相关联的动作。 如果没有确认到一个完全的匹配,则如果提供了使用通配符 _ 的最后一个 case 语句,则它将被用作已匹配模式。如果没有确认到一个完全的匹配并且不存在使用通配符的 case 语句,则整个 match 代码块不执行任何操作。
三.新的类型联合运算符
python3.10 中引入了启用 X | Y 语法的类型联合运算符。这提供了一种表示 '类型 X 或类型 Y' 的相比使用 typing.Union 更清晰的方式,特别是在类型提示中。在之前的 Python 版本中,要为可接受多种类型参数的函数应用类型提示。
def square(number: Union[int, float]) -> Union[int, float]:
return number ** 2
类型提示现在可以使用更简洁的写法:
def square(number: int | float) -> int | float:
return number ** 2
这个新增语法也被接受作为 isinstance() 和 issubclass() 的第二个参数:
>>> isinstance(1, int | str)
True
四.类型别名
python3.10 中 引入了类型别名的概念,只要求它们是不带标注的最高层级赋值。这种简单性有时会使得类型检查器难以区分类型别名和普通赋值,特别是当涉及到前向引用或无效类型的时候。
例如在比较:
StrCache = 'Cache[str]' # a type alias
LOG_PREFIX = 'LOG[DEBUG]' # a module constant
现在 typing 模块具有一个特殊值 TypeAlias 可让你更明确地声明类型别名:
StrCache: TypeAlias = 'Cache[str]' # a type alias
LOG_PREFIX = 'LOG[DEBUG]' # a module constant
04.错误信息更详细
在 python3.10 之前代码中的语法错误,大都错误提示信息都不精准,在 python3.10 中做了更多的优化处理
4.1、缺少括号的错误提示更完善
在 3.10 之代码如果你写的代码中缺少一个括号,运行代码抛出的错误信息中并不会准备的提示你哪个位置缺少括号,而是抛出一个不准确的错误信息。如下
a = {9: 1, 18: 2, 19: 2
b = 100
python3.10 之前:
File "demo.py", line 3
b = 100
^
SyntaxError: invalid syntax
但在 Python 3.10 中则提示更准确的错误信息:
python3.10:
File "demo.py", line 1
a = {9: 1, 18: 2, 19: 2
^
SyntaxError: '{' was never closed
4.2、语法错误的代码高亮标识
3.10 之前的语法错误显示
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
3.10 的语法错误显示
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
五、更多详细的错误提示场景
代码块之前缺失 :
>>> if rocket.position > event_horizon
File "<stdin>", line 1
if rocket.position > event_horizon
^
SyntaxError: expected ':'
5.1在多项集字面值中和表达式之间缺失逗号::
>>> items = {x: 1,y: 2 z: 3}
File "<stdin>", line 3
y: 2
^
SyntaxError: invalid syntax. Perhaps you forgot a comma?
多个异常类型捕获时不带圆括号:
>>> try:
... build_dyson_sphere()
... except NotEnoughScienceError, NotEnoughResourcesError:
File "<stdin>", line 3
except NotEnoughScienceError, NotEnoughResourcesError:
^
SyntaxError: multiple exception types must be parenthesized
字典字面值中缺失 : 和值:
>>> values = {x: 1,y: 2,z:}
File "<stdin>", line 4
z:
^
SyntaxError: expression expected after dictionary key and ':'
>>> values = {x:1, y:2, z w:3}
File "<stdin>", line 1
values = {x:1, y:2, z w:3}
^
SyntaxError: ':' expected after dictionary key
在比较中使用 = 而不是 ==:
>>> if rocket.position = event_horizon:
File "<stdin>", line 1
if rocket.position = event_horizon:
^
SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='?
try 代码块不带 except 或 finally 代码块:
>>> try:
... x = 2
... something = 3
File "<stdin>", line 3
something = 3
^^^^^^^^^
SyntaxError: expected 'except' or 'finally' block
5.2、IndentationError
代码缩进异常的意识更完善,会明确提示需要缩进的语句,包括语句的位置:
>>> def foo():
... if lel:
... x = 2
File "<stdin>", line 3
x = 2
^
IndentationError: expected an indented block after 'if' statement in line 2
5.3、AttributeError
当打印 AttributeError 时,将提供引发异常的对象中类似属性名称的建议:
>>> collections.namedtoplo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'collections' has no attribute 'namedtoplo'. Did you mean: namedtuple?
5.4、NameError
NameError 的错误信息中将提供引发异常的函数中类似变量名称的建议
>>> schwarzschild_black_hole = None
>>> schwarschild_black_hole
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?
六、其他语言特性修改
- int 类型新增了一个方法 int.bit_count(),返回给定整数的二进制展开中值为一的位数,或称“比特计量”。
- 现在 dict.keys(), dict.values() 和 dict.items() 所返回的视图都有一个 mapping 属性,它给出包装了原始字典的 types.MappingProxyType 对象
- PEP 618: 现在 zip() 函数有一个可选的 strict 旗标,用于要求所有可迭代对象的长度都相等。
- 接受整数参数的内置和扩展函数不再接受 Decimal, Fraction 以及其他可被转换为整数但会丢失精度(即具有 __int__() 方法但没有 index__()方法)的对象。
- 如果 object.__ipow__() 返回 NotImplemented,该运算符将正确地按照预期回退至 object.__pow__() 和 object.__rpow__()。
- 现在赋值表达式可以不带圆括号地在集合字面值和集合推导式中使用,也可以在序列索引号中使用(但不能用于切片)。
- 函数具有一个新的 __builtins__ 属性,当函数被执行时它会被用于查找内置符号,而不是在 __globals__['__builtins__'] 中查找。如果 __globals__["__builtins__"] 存在则该属性将基于它来初始化,否则将基于当前的内置函数。
- 增加了两个新的内置函数 —— aiter() 和 anext() 以分别提供与 iter() 和 next() 对应的异步版本。
- 静态方法 (@staticmethod) 和类方法 (@classmethod) 现在会继承方法属性 (__module__, __name__, __qualname__, __doc__, __annotations__) 并具有一个新的 __wrapped__ 属性。此外,静态方法现在还是与常规函数一样的可调用对象。
- 复杂目标的注解( PEP 526 定义的除 simple name 之外的一切复杂目标)在运行时不再受 from __future__ import annotations 的影响。
- 类和模块对象现在可以按需创建空的注解字典。为保证向下兼容,这些注解数据将存储于对象的 __dict__ 中。这改进了 __annotations__ 的最佳用法;
- 由于会产生副作用,现在 from __future__ import annotations 时禁止使用包含 yield 、 yield from 、 await 或已命名表达式的注解。
- 未绑定变量、super() 和其他可能改变符号表处理的表达式,现在在 from __future__ import annotations 时不能用作注解。
- float 类型和 decimal.Decimal 类型的 NaN 值的哈希值现在取决于对象身份。以前,即便 NaN 值彼此不等,也都是哈希为 0。在创建包含多个 NaN 的字典和集合时,由于哈希冲突过度,导致了运行代价可能会二次方增长。
七、福利大放送
需要下面资料的可以点击链接免费领取