PEP 839:PyFrozenSetWriter 和 PyFrozenDictWriter C API

PEP 839:PyFrozenSetWriter 和 PyFrozenDictWriter C API

💡 原文英文,约700词,阅读约需3分钟。
📝

内容提要

该文章提出为Python C API新增PyFrozenSetWriter和PyFrozenDictWriter两个构建器接口,遵循PEP 782的PyBytesWriter设计,允许直接逐项构建不可变的frozenset和frozendict,避免中间可变对象。同时软弃用对frozenset调用PySet_Add(),推荐使用新接口,并计划迁移CPython内部代码。

🔎

延伸解读

为什么需要新的构建器接口

当前C API构建frozenset或frozendict时,只能通过PyFrozenSet_New(iterable)或PyFrozenDict_New(iterable)一次性传入可迭代对象。若需逐项构建或合并多个映射,必须先创建中间可变容器(如dict)再复制,既低效又暴露可变中间态。新接口遵循PEP 782的PyBytesWriter设计,允许直接逐项添加,最终一次性生成不可变对象,避免中间容器。

软弃用PySet_Add()的意义

对frozenset调用PySet_Add()将被软弃用(PEP 387),但不会发出警告或安排移除。这意味着现有扩展模块仍可继续编译和运行,只是文档推荐改用PyFrozenSetWriter。软弃用为未来移除frozenset的可变性支持铺路,但移除需另立PEP。对set对象调用PySet_Add()则完全不受影响。

CPython内部迁移示例

CPython自身代码中存在多种构建frozenset/frozendict的模式,例如marshal.c中先构建dict再复制为frozendict。新接口允许直接使用PyFrozenDictWriter逐项写入,一次完成,且可指定大小提示。迁移后代码更简洁,也避免了中间对象的开销。

Q&A

PEP 839 提出了哪些新的 C API?

PEP 839 提出了两个新的 C API:PyFrozenSetWriter 和 PyFrozenDictWriter,用于直接构建不可变的 frozenset 和 frozendict。

PyFrozenSetWriter 和 PyFrozenDictWriter 的设计遵循了哪个 PEP 的什么模式?

它们遵循了 PEP 782 中 PyBytesWriter 的设计模式,即通过 writer 收集元素,最后通过 Finish() 一次性生成不可变对象,避免暴露中间可变对象。

为什么需要引入 PyFrozenSetWriter 和 PyFrozenDictWriter?

因为在 C API 中,构建 frozenset 或 frozendict 只能通过 PyFrozenSet_New(iterable) 或 PyFrozenDict_New(iterable) 一次性传入可迭代对象,如果逐项构建,必须先构建中间的可变容器(如 dict)再复制,效率低且不直接。新 API 允许逐项构建,无需中间容器。

PEP 839 对 PySet_Add() 在 frozenset 上的使用有何处理?

PEP 839 软弃用了对 frozenset 调用 PySet_Add(),推荐使用 PyFrozenSetWriter。但不会发出警告,也不会安排移除,现有扩展可以继续编译和运行。

PyFrozenSetWriter 和 PyFrozenDictWriter 的主要函数有哪些?

PyFrozenSetWriter 的主要函数有:PyFrozenSetWriter_Create(size_hint)、PyFrozenSetWriter_Add(writer, item)、PyFrozenSetWriter_Update(writer, iterable)、PyFrozenSetWriter_Finish(writer)、PyFrozenSetWriter_Discard(writer)。PyFrozenDictWriter 类似,但用 SetItem 代替 Add,Update 接受 mapping。

PEP 839 计划迁移哪些 CPython 内部代码?

计划迁移的 CPython 内部代码包括 Python/marshal.c 中的 TYPE_FROZENSET、Modules/_hashopenssl.c 中的 openssl_md_meth_names、Modules/_ssl.c 中的 ssl_enum_certificates、Modules/_abc.c 中的 __abstractmethods__、Modules/_asynciomodule.c 中的 _asyncio_awaited_by、Python/initconfig.c 中的 PyConfig_Names、Objects/codeobject.c、Python/compile.c、Python/flowgraph.c、Modules/_pickle.c 中的 load_frozenset 等。

PEP 839 是否计划移除 PySet_Add() 对 frozenset 的支持?

不,PEP 839 仅软弃用,移除支持留待未来的 PEP。

🏷️

标签

➡️

继续阅读