
Python 3.15 正式发布,带来惰性导入和 frozendict 等新特性
来源标题:The best new features in Python 3.15
Python 3.15 正式版发布,这是近年来功能最丰富的版本之一。新增惰性导入,可将模块导入延迟到实际使用时,降低程序启动开销;还加入了新的内置类型 frozendict,它不可变且可哈希。
以下正文由 AI 翻译自 InfoWorld(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
Python 3.15 是许久以来功能最丰富的 Python 版本之一,正式版刚刚发布。以下是其中最重大、最大胆、最重要的创新、变更与修复。
惰性导入(Lazy imports)
这是人们期盼已久的功能:惰性导入允许 import 只在程序真正用到时才被处理。对于那些导入缓慢、会给程序启动时间带来巨大开销的模块,你可以把这份开销推迟到该模块的代码真正执行时再付出。
你既可以使用新的惰性导入语法显式地启用惰性导入,也可以通过编程方式或环境变量,让使用常规导入写法的代码表现出惰性行为。这样一来,无需大量改写,就能让现有代码享受到这一特性。最妙的是,把导入变为惰性没有任何缺点:除此之外,它们的行为与预期完全一致。
内置类型 frozendict
Python 很少新增数据类型,但这一次是经过长期争论、期待已久的补充:冻结字典。frozendict 的行为与普通字典一样,区别在于它是不可变的(不能添加、删除或修改元素),而且是可哈希的(因此可以把它用作另一个字典的键等等)。
内置类型 sentinel()
语言中另一项新增内容,意在取代一种常见却有问题的 Python 写法:用 object() 创建一个唯一的哨兵对象(例如,当 None 本身可能是合法值时,用它作为 None 的替代)。新语法 sentinel("NAME") 会创建唯一的对象,这些对象只能通过 is 运算符与自身比较相等。这类对象可以被正确地做类型检查,并且拥有有意义的表示形式,而不只是一个随机的对象描述符。
Tachyon:统计采样分析器
长期存在的 cProfile 模块以确定性的方式对 Python 代码进行分析——也就是说,它会跟踪并记录每一次调用。这使它精确,但也意味着被 cProfile 跟踪的程序运行速度远低于正常水平。Python 3.15 中新增的分析模块 profiling.sampling 使用统计采样方法,在只对程序速度造成极小影响的情况下获取有用的性能信息。现有的 cProfile 分析器仍然可用——它不会消失——只是多了一个新名字:profiling.tracing。
升级版 JIT
CPython 内置的即时(JIT)编译器在 Python 3.13 中首次亮相。它的长期目标是在不修改任何代码的情况下让 Python 程序跑得更快,某种程度上类似于另一套 Python 运行时 PyPy 的加速方式,而且不必付出切换到一套完全不同、自身又有诸多限制的解释器的代价。
JIT 的前几个版本并没有承诺、也没有带来多少额外的速度提升,因为它们更多是在为未来的改进打基础。不过到了 Python 3.15,JIT 相比标准 CPython 已经展现出 8% 到 13% 的几何平均性能提升,具体幅度取决于平台和工作负载。最大的变化包括:新的跟踪前端(让更多种类的代码得以加速)、使用寄存器分配以实现更快更省内存的工作、JIT 生成更优质的机器码,以及诸如为某些类别的对象消除引用计数等额外优化。
值得一试的是,为你的工作负载启用 JIT,看看是否有可测量的差异。但要注意,JIT 的后续开发如今受到一些明确制定的准则约束,规定它必须提供多大的性能提升,才能被视为 Python 完全支持的一部分,而不仅仅是一个实验性的副线。
更完善的错误信息
在过去几个版本中,Python 的错误信息变得越来越精确、详细和有用,Python 3.15 延续了这一工作。亮点包括:
- 针对缺失名称的建议(“x has no attribute ‘y’。你是不是想用 ‘xyz’?”)现在会从给定对象的成员中给出建议,而不仅仅是从对象本身。
- 建议现在也覆盖删除属性的检查,而不仅仅是访问属性。
- 如果解释器无法基于 Levenshtein 距离的模糊名称匹配为某个方法给出建议,它会查阅一份其他语言中此类方法常用名称的列表。例如,如果你试图使用 list.push()(一个 JavaScript 方法),解释器会建议 .append(),这才是 Python 列表的正确方法。
类型系统改进
TypedDict 类允许你创建带有预定义键、并对键和值做类型提示的字典,现在其定义中新增支持两个参数。closed 参数让你可以指定运行时是否只能使用所指定的键。extra_items 参数让你可以在运行时指定额外的键,但仅限于值为指定类型的键。
TypeForm 类型定义让你可以表示对某个类型表达式求值后得到的结果。有了它,类型注解就可以用在那些把类型本身当作值来使用的地方——例如 typing.cast 甚至 isinstance 这类操作的各种变体,或者作为第三方类型检查工具工作方式的一部分。
推导式中的解包
这又是一个人们长期要求的功能。如果你想用推导式完全解包或“展平”一个嵌套对象,过去需要使用 itertools.chain() 这样的函数,或者写出语法丑陋的嵌套推导式:
x = [[1,2,3],[4,5],[6]]
y = [a for b in x for a in b]
>>> [1, 2, 3, 4, 5, 6] # y
在推导式中使用星号运算符进行解包,可以让你省去一步:
x = [[1,2,3],[4,5],[6]]
y = [*a for a in x]
>>> [1, 2, 3, 4, 5, 6] # y
用 ** 解包同样可行,例如作为一种展平并合并字典的方式:
dicts = [{'a': 1}, {'b': 2}, {'a': 3}]
y = {**d for d in dicts}
>>> {'a': 3, 'b': 2}
最后,这种解包也可以用来构造生成器表达式:
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。