PEP 802 – 空集的显示语法
- 作者:
- Adam Turner <adam at python.org>
- 讨论至:
- 待定
- 状态:
- 草案
- 类型:
- 标准跟踪
- 创建日期:
- 2025年8月8日
- Python 版本:
- 3.15
- 发布历史:
- 2025年8月8日
摘要
我们提出一种新符号 {/} 来构造和表示空集。这模仿了相应的数学符号“∅”。
这补充了现有的空元组、列表和字典的符号,它们分别使用 ()、[] 和 {}。
动机
集合是目前唯一的内置集合类型,它有显示语法,但没有表示空集合的符号。Python 语言参考手册 指出:
空集不能用{}构造;此字面量构造一个空字典。
这对于初学者来说可能令人困惑,尤其是那些从科学或数学背景学习该语言的人,因为在这些领域,集合可能比字典或映射更常用。
空集的语法符号有一个重要的好处,那就是不需要名称查找(不像 set())。{/} 将始终具有一致的含义,从而提高核心概念对初学者的可教性。例如,用户必须小心不要将 set 用作局部变量名,因为这样做会阻止构造新集合。这可能会令人沮丧,因为初学者可能不知道如何恢复 set 类型,如果他们已经覆盖了该名称。恢复它的技术(例如 type({1}))并不明显,尤其是对于那些正在学习该语言,可能还不熟悉 type 函数的人。
最后,这可能对非英语使用者有所帮助,因为它为语言内置的常见数据结构提供了一种无文化差异的表示方法。
基本原理
集合通过 PEP 218 引入到 Python 2.2 中,该 PEP 没有包含集合符号,但讨论了空集的 {-} 想法
PEP 最初提议{1,2,3}作为集合符号,{-}作为空集。Python 2.3 的sets.py的经验表明,这种符号没有必要。此外,还存在使字典不太容易识别的风险。
Python 3.0 引入了集合字面量(PEP 3100),但再次选择不引入空集的符号,出于实用主义而省略(python-3000,2006年4月,python-3000,2006年5月)。
自那时以来,该主题已被多次讨论,并提出了各种建议,包括
- 将
{}更改为空集,并使用{:}表示空字典(python-ideas,2008年1月,Discourse,2023年3月) - Unicode 字符(例如
∅或ϕ)(python-ideas,2021年4月) <>(python-ideas,2010年11月,Discourse,2024年12月)s{}(python-ideas,2009年6月){*()},也许优化将其编译为BUILD_SET操作码(Discourse,2025年8月 (#37)){-}(python-ideas,2020年8月)(/)(Discourse,2023年3月 (#20)){,}(Discourse,2025年8月){/}(python-ideas,2008年1月)set()(即什么都不做)
作者提议使用 {/} 作为表示符号,他们认为这是这些选项中最好的。它简单明了,并且具有与空集的数学符号 ∅ 相似的优点。这使得它比语言中的几个助记符(例如表示乘方的 ** 或表示矩阵乘法的 @)更容易解释。
{/} 符号在 最近的 Discourse 投票 中也最受欢迎,在所有受访者中占 41%,在投票支持新语法的受访者中占 60%。
其他提案的简要摘要可在 被拒绝的想法 中找到。
规范
集合显示的语法将变为
set_display ::= "{" ("/" | flexible_expression_list | comprehension) "}"
解析器将为 (/) 和 [/] 发出专门的错误消息,指示它们是无效语法,并分别建议空元组和列表的正确形式。
{/} 将成为空集的默认语法。
>>> type({/})
<class 'set'>
>>> {/} == set()
True
空集的表示和字符串形式将更改为 '{/}'。
>>> repr({/})
'{/}'
>>> repr(set())
'{/}'
>>> str({/})
'{/}'
>>> str(set())
'{/}'
set 对象的行为不会发生变化。
向后兼容性
依赖空集 repr() 或 str() 的代码将不再起作用,因为其表示将发生变化。
不会有其他向后不兼容的更改,所有当前空集构造函数将继续工作,set 类型的行为将保持不变。
因此,当前使用 set() 的代码将继续工作,并且可以保持不变。自动工具(如 linters 和 formatters)的开发人员应避免通过大规模建议将现有项目中的 set() 更改为 {/} 来鼓励“代码变动”,除非此类工具的用户明确要求。
安全隐患
无。
如何教授此内容
所有用户都可以被告知 {/} 是 set() 的新写法,并且在所有其他方面都等效。为了帮助加强这一点,我们将更新文档以使用 {/} 而不是 set(),包括教程、标准库模块和 Python 语言参考。
对于新用户,可以通过语法引入集合,并指出所有四个具有语法的内置集合类型都有空形式:()、[]、{/} 和 {}。
空集使用正斜杠将其与空字典区分开来。它使用此语法是因为它看起来像空集的数学符号(“∅”)。这可以作为教授初学者的有用助记符,特别是那些具有数学或科学背景的人。
参考实现
此 PEP 的参考实现作为 CPython 存储库在 Github 上的拉取请求存在:python/cpython#137565。
被拒绝的想法
将 {} 更改为空集,并使用 {:} 表示空字典
这将是一个完全向后不兼容的更改,所有当前的空 dict 对象都将变成集合。
使用 Unicode 字符(例如 ∅ 或 ϕ)
Unicode 字符“U+2205 ∅ EMPTY SET”目前不是有效的标识符。引入 Unicode 字符作为语法将很难使用,因为它不出现在标准键盘上。
使用其他看起来像 ∅ 的字符,例如“U+03C6 ϕ GREEK SMALL LETTER PHI”或“U+00D8 Ø LATIN CAPITAL LETTER O WITH STROKE”,会更令人困惑,并且具有使用 Unicode 字符相同的缺点。
使用 <> 语法
它与非空集的语法没有相似之处。这比本 PEP 的提案更难解释。
这种语法在历史上还用作不等于运算符,仍然可以通过 from __future__ import barry_as_FLUFL 访问。同时使用 barry_as_FLUFL 未来导入和 <> 表示空集将导致解析器歧义:<> <> <> 将意味着什么?
使用 s{} 语法
此语法可能与局部变量 s 引起混淆。目前这种前缀的唯一用途是字符串字面量。这比本 PEP 的提案更难解释。
使用 {*()} 语法
这依赖于将空元组解包到集合中,从而创建一个空集。这自 Python 3.5 起就得到了支持(PEP 448),因此具有优势。
解释此符号需要理解序列解包、空元组、集合字面量语法以及解包空序列而不产生任何值进行解包的概念。
这是一种笨拙的语法;不容易教给初学者。我们应该避免引入复杂的符号,并假定用户以后会理解它,或者可以在网上查找。这剥夺了学习者的自主权。尤其是在使用可以执行任意代码的编程语言时,用户理解他们正在编写的代码的作用非常重要。
在作者看来,将 {*()} 推广为空集的语法将是一个错误。它是 PEP 448 的副作用,而不是有意设计易于教学、理解和解释的语法。
使用 {-} 语法
此语法最初在 PEP 218 中提出,但在被接受之前从 PEP 中删除。作者更喜欢 {/},因为它与 ∅ 相似。
使用 (/) 语法
有人建议这种符号更好地视觉上模仿空集符号(例如 U+2205 ∅ EMPTY SET)。然而,它与常规集合语法完全不同。对作者来说,任何带有大括号的建议符号都优于此提案,因为它们与当前(自 Python 3.0 起)的集合符号更一致。
作者更喜欢 {/},因为它结合了与数学符号和现有集合语法在视觉上相似的优点,而不像 (/)。
使用 {,} 语法
这是作者第二优先的选择。然而,如果使用单个逗号来表示空集合,那么为什么不能将其用于空元组或列表可能会令人困惑。随着时间的推移,可能会有人提议添加对 [,] 和 (,) 的支持。这与“应该有一种——最好只有一种——显而易见的方法”的普遍原则相冲突。使用明显不同的形式,即 {/},有助于强化空集语法是一个特殊情况,而不是所有空集合的通用规则的想法。
为 '{/}' 创建并使用新标记
此前有提议为此构造创建一个新标记。这将要求 '{/}' 被字面写入,字符之间没有空格。
我们选择允许括号和斜杠之间有空格,将 {、/ 和 } 视为三个不同的标记,因为我们看不到任何阻止这样做的理由。但是,我们预计绝大多数用途不会包含空格。
未解决的问题
无。
致谢
- Chris Angelico、Dominykas Grigonis、Ben Hsing、James Webber 以及最近 Discourse 主题的其他贡献者。
- Hugo van Kemenade,感谢他对 PEP 草案的有用反馈。
版权
本文档置于公共领域或 CC0-1.0-Universal 许可证下,以更宽松者为准。
来源:https://github.com/python/peps/blob/main/peps/pep-0802.rst