一篇文章带你快速了解python3.10的新特性
python3.10的预发布版已经出来了,今天和大家一起快速盘点一下python3.10中新增的哪些新的特性。
一、上下文管理器
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
五、错误信息更详细
5.1、SyntaxError
在python3.10之前代码中的语法错误,大都错误提示信息都不精准,在python3.10中做了更多的优化处理,
一、缺少括号的错误提示更完善
在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
二、语法错误的代码高亮标识
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 ':'
在多项集字面值中和表达式之间缺失逗号: :
>>> 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 的字典和集合时,由于哈希冲突过度,导致了运行代价可能会二次方增长。
欢迎来到testingpai.com!
注册 关于