What’s New In Python 3.11
Python 3.11 is between 10-60% faster than Python 3.10. On average, we measured a 1.25x speedup on the standard benchmark suite. See Faster CPython for details.
- 总的来说, 有一些纯Python的性能优化比较明显
- 异步调度也更加友好了
Important
PEP 678: Exceptions can be enriched with notes
通过add_note 方法为BaseEexception添加上下文相关的注释.
Example
try:
raise TypeError('bad type')
except Exception as e:
e.add_note('Add some information')
raise
asyncio
TaskGroup
Added cancelling() and uncancel() methods to Task. These are primarily intended for internal use, notably by TaskGroup.
通过异步上下文并发控制多个异步任务,并等待全部结束
Example
import asyncio
async def task1():
await asyncio.sleep(1)
print("task1 finished")
return "result1"
async def task2():
await asyncio.sleep(2)
print("task2 finished")
return "result2"
async def main():
async with asyncio.TaskGroup() as tg:
t1 = tg.create_task(task1())
t2 = tg.create_task(task2())
# 当退出async with时,TaskGroup已确保所有任务完成
print(f"task1 result: {t1.result()}")
print(f"task2 result: {t2.result()}")
asyncio.run(main())
timeout
使用asyncio.timeout上下文管理器代替asyncio.wait_for以控制超时调度
Example
import asyncio
async def long_running_task():
await asyncio.sleep(5)
return "task completed"
async def main():
try:
# 设置超时时间为3秒,超过时间未完成则抛出TimeoutError
async with asyncio.timeout(3):
result = await long_running_task()
print(result)
except TimeoutError:
print("任务执行超时")
asyncio.run(main())
Runner
asyncio.Runner 允许在同一线程内多次调度异步协程代码, 避免重复创建/关闭事件循环带来的性能和安全隐患
Example
import asyncio
async def main():
await asyncio.sleep(1)
print("hello")
# 使用 Runner 作为上下文管理器,运行异步函数
with asyncio.Runner() as runner:
runner.run(main())
Others
Path.glob()和Path.rglob()路径参数以/结尾时, 只返回路径不返回文件
Nice
PEP 657: Fine-grained error locations in tracebacks
异常打印显示的错误颗粒度更细了
Example
Traceback (most recent call last):
File "distance.py", line 11, in <module>
print(manhattan_distance(p1, p2))
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "distance.py", line 6, in manhattan_distance
return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y)
^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'x'
Type Hints
PEP 646: Variadic generics
可变参数泛型注解, 允许定义泛型类接受任意数量和类型的类型参数
Example
from typing import Generic, TypeVar, TypeVarTuple
Ts = TypeVarTuple('Ts')
class Array(Generic[*Ts]):
def __init__(self, *values: *Ts):
self.values = values
def add_dimension(self, value) -> 'Array[*Ts, type(value)]':
return Array(*self.values, value)
a = Array[int, str](1, 'foo')
print(a.values) # (1, 'foo')
b = a.add_dimension(3.14)
print(b.values) # (1, 'foo', 3.14)
PEP 655: Marking individual TypedDict items as required or not-required
允许在 TypedDict 中单独为key 标记必需或可选
Example
from typing import TypedDict, NotRequired, Required
class Movie(TypedDict):
title: Required[str]
director: NotRequired[str]
year: Required[int]
rating: NotRequired[float]
movie1: Movie = {
"title": "Inception",
"year": 2010,
# "director" 和 "rating" 可以省略
}
movie2: Movie = {
"title": "The Matrix",
"director": "The Wachowskis",
"year": 1999,
"rating": 8.7,
}
PEP 673: Self type
使用 typing.Self 注解返回值为该类的实例
Example
class MyLock:
def __enter__(self) -> Self:
self.lock()
return self
...
class MyInt:
@classmethod
def fromhex(cls, s: str) -> Self:
return cls(int(s, 16))
...
PEP 675: Arbitrary literal string type
typing.LiteralString 标注任意的字面量字符串类型
Example
def run_query(sql: LiteralString) -> ...
...
def caller(
arbitrary_string: str,
query_string: LiteralString,
table_name: LiteralString,
) -> None:
run_query("SELECT * FROM students") # ok
run_query(query_string) # ok
run_query("SELECT * FROM " + table_name) # ok
run_query(arbitrary_string) # type checker error
run_query( # type checker error
f"SELECT * FROM students WHERE name = {arbitrary_string}"
)
asyncio
asyncio.StreamWriter.start_tls
Added the asyncio.StreamWriter.start_tls() method for upgrading existing stream-based connections to TLS. (Contributed by Ian Good in bpo-34975.)
enum
verify
为 Enum 类增加约束检查, 很方便
Example
from enum import Enum, verify, UNIQUE, CONTINUOUS, NAMED_FLAGS, Flag
# 检查枚举值唯一
@verify(UNIQUE)
class ColorUnique(Enum):
RED = 1
GREEN = 2
BLUE = 3
# CRIMSON = 1 # 如果取消注释,会抛出 ValueError,提示有别名
# 检查枚举值连续
@verify(CONTINUOUS)
class ColorContinuous(Enum):
RED = 1
GREEN = 2
BLUE = 3
# FOUR = 5 # 如果取消注释,会抛出 ValueError,提示缺少中间值 4
# 检查 Flag 枚举的组合值必须对应已命名的标志
@verify(NAMED_FLAGS)
class ColorFlags(Flag):
RED = 1
GREEN = 2
BLUE = 4
WHITE = 7 # 7是RED|GREEN|BLUE的组合,合法
# INVALID = 8 # 如果取消注释,因组合值无对应命名标志,会抛出 ValueError
print(list(ColorUnique))
print(list(ColorContinuous))
print(list(ColorFlags))
member、nomember
允许为 Enum 添加方法作为成员/非成员属性
Example
from enum import Enum, member, nonmember
class Menu(Enum):
NEW = "NewGame"
LOAD = "LoadGame"
@member
@staticmethod
def QUIT():
return "QuitGame"
@nonmember
def helper(self):
return f"Help for {self.name}"
# 访问枚举成员
print(Menu.NEW)
print(Menu.QUIT)
# helper 不会作为成员出现
print(hasattr(Menu, 'helper')) # True
print('helper' in Menu.__members__) # False
print(Menu.NEW.helper()) # 调用普通方法
peoperty
为枚举成员而不是枚举类本身添加计算属性, 避免和枚举成员名称冲突
Example
from enum import Enum, property
class Planet(Enum):
MERCURY = 0.39
VENUS = 0.72
EARTH = 1.00
@property
def distance_au(self):
# 返回距离太阳的天文单位(AU)
return self.value
@property
def distance_km(self):
# 根据AU换算公里,1 AU ≈ 1.496e8 km
return self.value * 1.496e8
print(Planet.EARTH.distance_au) # 输出: 1.0
print(Planet.EARTH.distance_km) # 输出: 149600000.0
global_enum
- 将枚举类的成员提升到模块的属性
Example
from enum import global_enum, Enum
import cmath
@global_enum
class Constants(float, Enum):
PI = cmath.pi
E = cmath.e
print('PI' in globals()) # True
print('E' in globals()) # True
Flag
操作支持
enum.Flag 支持len 、in、not in 操作
Example
from enum import Flag, auto
class AFlag(Flag):
ONE = auto() # 1
TWO = auto() # 2
FOUR = auto() # 4
combined = AFlag.ONE | AFlag.TWO # 组合
print(len(combined)) # 输出 2,因为组合中包含两个标志成员
print(list(combined)) # 输出 [AFlag.ONE, AFlag.TWO]
print(AFlag.ONE in combined) # True,检查成员是否包含
print(AFlag.FOUR in combined) # False
primary values and aliases
将 Flag 的成员分为主值和别名, 别名用主值的组合表现
Example
from enum import Flag, auto
class Color(Flag):
RED = auto() # 1
GREEN = auto() # 2
BLUE = auto() # 4
WHITE = RED | GREEN | BLUE # 7
print(list(Color))
# 输出: [<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 4>]
# WHITE 不在列表中,因为它是组合值,不是主值
print(~Color.RED)
# 输出: <Color.GREEN|BLUE: 6>,取反得到正等价组合而非负值
Trivial
PEP654: Exception Groups and except*
支持嵌套的异常组并支持在捕获异常时提取组内的异常多次处理
Example
from builtins import ExceptionGroup
def test():
raise ExceptionGroup(
"Multiple errors",
[
ValueError("Invalid value"),
ExceptionGroup(
"Nested group",
[
ImportError("No module found"),
ModuleNotFoundError("Another module missing")
]
),
TypeError("Wrong type")
]
)
try:
test()
except* ValueError as e:
print("Caught ValueError:", e)
except* ImportError as e:
print("Caught ImportError:", e)
Type Hints
PEP 681: Data class transforms
为静态类型检查器标识某个类支持数据类的特点, 以自动推断使用.
Example
from typing import dataclass_transform
@dataclass_transform()
def my_dataclass(cls):
return cls
@my_dataclass
class Point:
x: int
y: int
p = Point()
p.x = 10
p.y = 20
print(p.x, p.y)
asyncio
all_errors to the asyncio.loop.create_connection
Added keyword argument all_errors to asyncio.loop.create_connection() so that multiple connection errors can be raised as an ExceptionGroup.
some raw datagram functions to the event loop
Added raw datagram socket functions to the event loop: sock_sendto(), sock_recvfrom() and sock_recvfrom_into(). These have implementations in SelectorEventLoop and
contextlib.chdir
用于临时切换工作目录时一个非常方便的上下文管理器, 需要注意的是非并发安全.
Example
import os
from contextlib import chdir
print("当前工作目录:", os.getcwd())
with chdir("/tmp"):
print("临时切换到目录:", os.getcwd())
# 在这里执行需要在 /tmp 下完成的操作
print("恢复到原工作目录:", os.getcwd())
New Modules
- 内置关于
toml的解析库 wsgiref.types为静态类型检查提供WSGI协议方面的支持
Others
[b for a, *b in ([1,2,3], [4,5,6])]支持在for语句中使用*解包- 在异步协程函数中支持异步协程推导表达式, 如
[x asynx for x in async_func()] - 不支持上下文管理器的对象中使用 with 语句将会抛出
TypeError而不是AttributeError - 添加
object.__getstate__默认实现 - 添加
-P命令和PYTHONSAFEPATH环境变量以阻止自动将脚本目录添加到sys.path sys.path不再接受bytes对象dataclass目前接受可哈希的对象作为参数默认值datetime.UTC->datetime.timezone.utcdatetime下一些子模块支持解析大多数的ISO8601格式的字符串enum.EnumMeta重命名为enum.EnumType- 新增
enum.StrEnum gzip.compress在mktime=0时速度更快了- 新增
locale.getencoding() - 新增
logging.getLevelNamesMapping()返回日志级别名称和数值的映射 - 新增
math.exp2返回 2 的 x 次方 math.nan永久可用- 新增
operator.call以调用一个对象的可执行方法 re支持原子分组和占有量词特性- 当Unix上C库支持
sem_clockwait函数时,threading.Lock.acquire()将使用time.CLOCK_MONOTONIC代替time.CLOCK_REALTIME zipfile.Path新增stem、suffix、suffixes属性
总结
- 说是比 3.10 平均快了 1.25 倍
- 异常打印更友好了
- 异常捕获时可以通过
add_note添加关于上下文的注释, 对于异常信息回溯处理更灵活 - 使用
asyncio.TaskGroup并发控制一组异步协程任务 - 使用
asyncio.timeout控制异步协程的超时调度 asyncio.Runner允许在同一线程内多次调度异步协程代码, 避免重复创建/关闭事件循环带来的性能和安全隐患dataclass目前接受可哈希的对象作为参数默认值enum.verify装饰器为Enum类增加约束检查enum.member、enum.nomember允许为Enum添加方法作为成员/非成员属性enum.property为Enum类添加基于成员的计算属性Path.glob()和Path.rglob()路径参数以/结尾时, 只返回路径不返回文件re支持原子分组和占有量词特性- 当Unix上C库支持
sem_clockwait函数时,threading.Lock.acquire()将使用time.CLOCK_MONOTONIC代替time.CLOCK_REALTIME