Python 3.9 新特性全面总结
发布时间:2020 年 10 月 5 日
一、重磅新语法
1. 字典合并运算符 | 和 |=(PEP 584)
终于不用再写 {**d1, **d2} 了!
python
x = {"a": 1, "b": 2}
y = {"b": 99, "c": 3}
# 合并(新建字典,右侧优先)
z = x | y # {'a': 1, 'b': 99, 'c': 3}
# 原地更新(类似 dict.update)
x |= y # x 变为 {'a': 1, 'b': 99, 'c': 3}
注意:
|不修改原字典,|=会修改左侧字典。
2. 内置类型直接用于类型标注(PEP 585)
以前写类型提示必须从 typing 导入 List、Dict 等大写版本,现在可以直接用内置类型:
python
# 旧写法(3.8 及以前)
from typing import List, Dict, Tuple
def foo(names: List[str]) -> Dict[str, int]: ...
# 新写法(3.9+)
def foo(names: list[str]) -> dict[str, int]: ...
支持的类型包括:list、dict、tuple、set、frozenset,以及 queue.Queue 等标准库类型。
3. 字符串新增 removeprefix / removesuffix(PEP 616)
告别 lstrip 的误用,精准移除前缀/后缀:
python
"Hello, World!".removeprefix("Hello, ") # 'World!'
"Hello, World!".removesuffix(", World!") # 'Hello'
# 如果前/后缀不存在,原样返回
"Python".removeprefix("Java") # 'Python'
bytes、bytearray、collections.UserString 同样支持。
4. 装饰器语法放宽(PEP 614)
之前装饰器只能是简单的名称或属性访问,现在任意合法表达式都可以作为装饰器:
python
# 现在合法了
button_list[0].clicked.connect
@button_list[0].clicked.connect
def slot(): ...
二、新增模块
1. zoneinfo --- 时区支持(PEP 615)
标准库终于内置了 IANA 时区数据库支持,不再需要第三方 pytz:
python
from zoneinfo import ZoneInfo
from datetime import datetime
dt = datetime(2024, 6, 1, 12, tzinfo=ZoneInfo("Asia/Shanghai"))
print(dt) # 2024-06-01 12:00:00+08:00
在没有系统时区数据的平台(如 Windows),可通过
pip install tzdata安装数据包。
2. graphlib --- 拓扑排序
新增 graphlib.TopologicalSorter,用于有向无环图的拓扑排序,适合任务依赖调度等场景:
python
from graphlib import TopologicalSorter
graph = {"D": {"B", "C"}, "C": {"A"}, "B": {"A"}}
ts = TopologicalSorter(graph)
print(list(ts.static_order())) # ['A', 'C', 'B', 'D'] 或类似顺序
三、标准库改进(常用部分)
math 模块增强
python
import math
math.gcd(12, 18, 24) # 支持多个参数了,返回 6
math.lcm(4, 6, 10) # 新增!最小公倍数,返回 60
math.nextafter(1.0, 2.0) # 新增!返回 1.0 往 2.0 方向的下一个浮点数
math.ulp(1.0) # 新增!返回浮点数的最小精度单位
asyncio 改进
- 新增
asyncio.to_thread():将同步阻塞函数放到线程池执行,避免阻塞事件循环:
python
import asyncio
def blocking_io():
# 模拟耗时 IO
...
async def main():
await asyncio.to_thread(blocking_io)
asyncio.wait_for()超时取消行为更可靠- 移除了
asyncio.Task.current_task()和asyncio.Task.all_tasks()(已在 3.7 弃用),请用asyncio.current_task()和asyncio.all_tasks()
typing 模块
新增 typing.Annotated,可以为类型附加额外元数据(如校验规则、文档说明等):
python
from typing import Annotated
# 附加元数据,不影响运行时类型检查,供框架(如 FastAPI)使用
Positive = Annotated[int, "must be positive"]
random 模块
新增 random.randbytes(n):生成 n 个随机字节:
python
import random
random.randbytes(8) # b'\x9f\x12...'
pathlib 模块
新增 Path.readlink(),读取符号链接目标路径(等价于 os.readlink())。
concurrent.futures 改进
Executor.shutdown() 新增 cancel_futures=True 参数,可立即取消所有未开始的任务,不必等待它们完成。
ipaddress 模块
- 支持 IPv6 作用域地址(
%scope_id格式) - 注意(3.9.5+) :不再接受 IPv4 地址中带前缀零的写法(如
010.0.0.1),避免八进制歧义
四、解释器与性能优化
新 PEG 解析器(PEP 617)
CPython 从 LL(1) 解析器切换到基于 PEG 的新解析器,性能相当,但为未来新语法特性提供更大灵活性。Python 3.10 起旧解析器被彻底移除。
内置类型 vectorcall 加速
range、tuple、set、frozenset、list、dict 等内置类型通过 PEP 590 vectorcall 协议加速,函数调用开销更低。
其他优化
- 多线程信号处理优化:非主线程不再每条字节码都检查信号,减少不必要的中断
- UTF-8 / ASCII 短字符串解码速度提升约 15%
ProcessPoolExecutor工作进程按需创建,减少空闲进程的 CPU 浪费- 垃圾回收不再因复活对象而阻塞其他不可达对象的回收
五、弃用警告(需要注意)
| 弃用内容 | 说明 | 替代方案 |
|---|---|---|
collections.Mapping 等别名 |
Python 3.9 是最后支持版本,3.10 移除 | 改用 collections.abc.Mapping 等 |
parser 和 symbol 模块 |
随旧解析器一起弃用 | 改用 ast 模块 |
math.factorial(float) |
不再接受浮点数参数 | 传入整数 |
asyncio.wait() 传入协程对象 |
将在 3.11 移除 | 改传 Task 或 Future |
random.shuffle(x, random=...) |
random 参数弃用 |
直接调用 random.shuffle(x) |
lib2to3 模块 |
发出 PendingDeprecationWarning | 考虑 LibCST 或 parso |
GzipFile 写入不指定 mode |
未来默认改为读取 | 显式传入 mode='wb' |
六、正式移除(升级必看)
这些 API 在 3.9 中已彻底删除,升级时需检查代码:
| 移除内容 | 替代方案 |
|---|---|
array.tostring() / fromstring() |
tobytes() / frombytes() |
threading.Thread.isAlive() |
is_alive() |
base64.encodestring() / decodestring() |
encodebytes() / decodebytes() |
fractions.gcd() |
math.gcd() |
json.loads(encoding=...) |
直接传字符串,无需指定编码 |
asyncio.Task.current_task() / all_tasks() |
asyncio.current_task() / asyncio.all_tasks() |
ElementTree.getchildren() / getiterator() |
list(x) / x.iter() |
sys.getcheckinterval() / setcheckinterval() |
sys.getswitchinterval() / setswitchinterval() |
_dummy_thread / dummy_threading 模块 |
已无替代,直接移除 |
with (await asyncio.lock): 语法 |
async with lock: |
七、其他值得关注的小变化
__main__.__file__改为绝对路径 :python3 script.py时__file__不再是相对路径,os.chdir()后仍然有效sys.stderr改为行缓冲:非交互模式下 stderr 不再是块缓冲,日志输出更及时datetime.isocalendar()返回 namedtuple :可以用.year、.week、.weekday访问字段logging.getLogger('root')行为变化 :现在返回真正的根日志器,而非名为root的普通日志器- Unicode 数据库升级到 13.0
总结
Python 3.9 的核心亮点:
|字典合并运算符 --- 最受欢迎的语法糖之一- 内置类型直接用于类型标注 --- 告别
from typing import List str.removeprefix/removesuffix--- 简洁实用zoneinfo时区模块 --- 标准库终于有了靠谱的时区支持- PEG 解析器 --- 为未来语法扩展铺路
同时这也是 Python 2 兼容层的最后一个版本 ,collections.Mapping 等别名将在 3.10 彻底消失,建议尽早迁移。
参考:Python 3.9 官方文档 - What's New
内容由 AI 整理生成,内容仅供参考,请仔细甄别。