内容提要
PEP 749 旨在补充 PEP 649,改进 Python 注解的语义。新增的 annotationlib 模块提供了 get_annotations() 函数和 ForwardRef 类。PEP 563 的未来导入将被弃用,注解将延迟评估,以确保一致性。该提案还解决了注解与元类的交互问题,并引入了 VALUE_WITH_FAKE_GLOBALS 格式,以增强对第三方实现的支持。
延伸解读
从 __future__ 导入的弃用时间表
PEP 749 为 from __future__ import annotations 制定了明确的弃用路线:在 Python 3.14 中它仍按原行为工作,将注解转为字符串;待最后一个不支持 PEP 649 语义的版本(预计为 3.13)结束生命周期后,该 future 导入才会被弃用,编译使用它的代码将发出 DeprecationWarning;再经过至少两个版本后移除,届时使用它会引发 SyntaxError。这意味着开发者有多年时间逐步移除该导入,但需注意依赖字符串化注解的代码最终必须调整。
annotationlib 模块的定位与工具
新标准库模块 annotationlib 专门用于注解的内省与包装,避免将相关工具塞进庞大的 inspect 模块。它提供 get_annotations() 函数、Format 枚举、ForwardRef 类以及 call_annotate_function 等辅助函数。其中 ForwardRef 取代了 typing.ForwardRef,保留已弃用的 _evaluate 方法以兼容现有第三方库,同时新增公开的 evaluate 方法。该模块从设计之初就作为公开 API,以便标准库和第三方实现都能一致地支持 P
元类与注解交互的修复
PEP 649 的延迟求值使类与元类之间的注解交互更易出错,例如元类的注解可能泄漏到其实例类。PEP 749 最终采用将 __annotate__ 和 __annotations__ 存储在类字典中但使用内部名称的方案,避免干扰 type 上的描述符,从而让类对象的这两个属性在自定义元类存在时仍能可靠返回。不过,在 from __future__ import annotations 下,类字典仍保留 __annotations__ 条目,因此部分旧有错误行为会延续;同时,实例上访问 __annotations__
新增格式与条件注解支持
PEP 749 引入 VALUE_WITH_FAKE_GLOBALS 格式,供编译器生成的 __annotate__ 函数在“假全局”环境中使用,第三方手写函数应在此格式下抛出 NotImplementedError。同时,SOURCE 格式更名为 STRING,以更准确反映其返回字符串字典的行为。此外,针对 if TYPE_CHECKING 等条件定义的类或模块注解,PEP 749 通过为每个注解分配唯一标识符并记录已执行集合,使 __annotate__ 只返回实际定义的注解,恢复了这一常见模式的可预期行为。
Q&A
PEP 749 的主要目标是什么?
PEP 749 旨在补充 PEP 649,改进 Python 注解的语义。
annotationlib 模块提供了哪些新功能?
annotationlib 模块提供了 get_annotations() 函数和 ForwardRef 类等功能。
PEP 563 的未来导入将如何变化?
PEP 563 的未来导入将被弃用,注解将延迟评估,以确保一致性。
VALUE_WITH_FAKE_GLOBALS 格式的作用是什么?
VALUE_WITH_FAKE_GLOBALS 格式增强了对第三方实现的支持,允许在“假全局”环境中运行注解函数。
删除 __annotations__ 属性会有什么后果?
删除 __annotations__ 属性将导致 __annotate__ 属性被设置为 None。
PEP 749 如何解决注解与元类的交互问题?
PEP 749 通过确保 __annotate__ 和 __annotations__ 属性在类对象中可靠返回,解决了注解与元类的交互问题。