|
| 1 | +PEP: 802 |
| 2 | +Title: Display Syntax for the Empty Set |
| 3 | +Author: Adam Turner < [email protected]> |
| 4 | +Discussions-To: Pending |
| 5 | +Status: Draft |
| 6 | +Type: Standards Track |
| 7 | +Created: 08-Aug-2025 |
| 8 | +Python-Version: 3.15 |
| 9 | + |
| 10 | + |
| 11 | +Abstract |
| 12 | +======== |
| 13 | + |
| 14 | +We propose a new notation, ``{/}``, to construct and represent the empty set. |
| 15 | +This is modelled after the corresponding mathematical symbol ':math:`\emptyset`'. |
| 16 | + |
| 17 | +This complements the existing notation for empty tuples, lists, and |
| 18 | +dictionaries, which use ``()``, ``[]``, and ``{}`` respectively. |
| 19 | + |
| 20 | + |
| 21 | +Motivation |
| 22 | +========== |
| 23 | + |
| 24 | +Sets are currently the only built-in collection type that have a |
| 25 | +:ref:`display syntax <python:comprehensions>`, |
| 26 | +but no notation to express an empty collection. |
| 27 | +The :ref:`Python Language Reference <python:set>` notes this, stating: |
| 28 | + |
| 29 | + An empty set cannot be constructed with ``{}``; |
| 30 | + this literal constructs an empty dictionary. |
| 31 | + |
| 32 | +This can be confusing for beginners, especially those coming to the language |
| 33 | +from a scientific or mathematical background, where sets may be in more common |
| 34 | +use than dictionaries or maps. |
| 35 | + |
| 36 | +A syntax notation for the empty set has the important benefit of not requiring |
| 37 | +a name lookup (unlike ``set()``). |
| 38 | +``{/}`` will always have a consistent meaning, improving teachability |
| 39 | +of core concepts to beginners. |
| 40 | +For example, users must be careful not to use ``set`` as a local variable name, |
| 41 | +as doing so prevents constructing new sets. |
| 42 | +This can be frustrating as beginners may not know how to recover the |
| 43 | +:py:class:`set` type if they have overriden the name: |
| 44 | +techniques to do so (e.g. ``type({1}-{1})``) are not immediately obvious. |
| 45 | + |
| 46 | +Finally, this may be helpful for users who do not speak English, |
| 47 | +as it provides a culture-free notation for a common data structure |
| 48 | +that is built into the language. |
| 49 | + |
| 50 | + |
| 51 | +Rationale |
| 52 | +========= |
| 53 | + |
| 54 | +Sets were introduced to Python 2.2 via :pep:`218`, which did not include |
| 55 | +set notation, but discussed the idea of ``{-}`` for the empty set: |
| 56 | + |
| 57 | + The PEP originally proposed ``{1,2,3}`` as the set notation and ``{-}`` for |
| 58 | + the empty set. Experience with Python 2.3's ``sets.py`` showed that |
| 59 | + the notation was not necessary. Also, there was some risk of making |
| 60 | + dictionaries less instantly recognizable. |
| 61 | + |
| 62 | +Python 3.0 introduced set literals (:pep:`3100`), but again chose not to |
| 63 | +introduce notation for the empty set, which was omitted out of pragmatism |
| 64 | +(`python-3000, April 2006`_, `python-3000, May 2006`_). |
| 65 | + |
| 66 | +Since then, the topic has been discussed several times, |
| 67 | +with various proposals, including: |
| 68 | + |
| 69 | +#. Changing ``{}`` to mean an empty set and using ``{:}`` for an empty dictionary |
| 70 | + (`python-ideas, January 2008`_, `Discourse, March 2023`_) |
| 71 | +#. A Unicode character (e.g. ``∅`` or ``ϕ``) |
| 72 | + (`python-ideas, April 2021`_) |
| 73 | +#. ``<>`` |
| 74 | + (`python-ideas, November 2010`_, `Discourse, December 2024`_) |
| 75 | +#. ``s{}`` |
| 76 | + (`python-ideas, June 2009`_) |
| 77 | +#. ``{*()}``, perhaps optimising to compile this to the ``BUILD_SET`` opcode |
| 78 | + (`Discourse, August 2025 (#37)`_) |
| 79 | +#. ``{-}`` |
| 80 | + (`python-ideas, August 2020`_) |
| 81 | +#. ``{,}`` |
| 82 | + (`Discourse, August 2025`_) |
| 83 | +#. ``{/}`` |
| 84 | + (`python-ideas, January 2008`_) |
| 85 | +#. ``set()`` (i.e. doing nothing) |
| 86 | + |
| 87 | +The authors propose ``{/}`` as the notation, |
| 88 | +being in their opinion the best of these options. |
| 89 | +It is simple and concise, with the benefit of resembling the mathematical |
| 90 | +notation for the empty set, :math:`\emptyset`. |
| 91 | +This makes it an easier mnemonic to explain than several in the language, |
| 92 | +such as ``**`` for exponentiation or ``@`` for matrix multiplication. |
| 93 | + |
| 94 | +The ``{/}`` notation was also the most popular in a `recent Discourse poll`_, |
| 95 | +selected by 41% of respondents overall and 60% of those voting for a new syntax. |
| 96 | + |
| 97 | +Brief summaries for the other proposals may be found in `Rejected Ideas`_. |
| 98 | + |
| 99 | + |
| 100 | +Specification |
| 101 | +============= |
| 102 | + |
| 103 | +The grammar for set displays will become: |
| 104 | + |
| 105 | +.. productionlist:: python-grammar |
| 106 | + set_display: "{" ("/" | flexible_expression_list | comprehension) "}" |
| 107 | + |
| 108 | +``{/}`` will become the default syntax for the empty set. |
| 109 | + |
| 110 | +.. code-block:: python |
| 111 | +
|
| 112 | + >>> type({/}) |
| 113 | + <class 'set'> |
| 114 | + >>> {/} == set() |
| 115 | + True |
| 116 | +
|
| 117 | +The representation and string forms of the empty set will change to ``'{/}'``. |
| 118 | + |
| 119 | +.. code-block:: python |
| 120 | +
|
| 121 | + >>> repr({/}) |
| 122 | + '{/}' |
| 123 | + >>> str({/}) |
| 124 | + '{/}' |
| 125 | +
|
| 126 | +There will be no behavioural changes to :py:class:`set` objects. |
| 127 | + |
| 128 | + |
| 129 | +Backwards Compatibility |
| 130 | +======================= |
| 131 | + |
| 132 | +Code that relies on the ``repr()`` or ``str()`` of the empty set |
| 133 | +will no longer work, because the representation will change. |
| 134 | + |
| 135 | +There will be no other backwards incompatibile changes, |
| 136 | +all current constructors for the empty set will continue to work, |
| 137 | +and the behaviour of the :py:class:`set` type will remain unchanged. |
| 138 | + |
| 139 | + |
| 140 | +Security Implications |
| 141 | +===================== |
| 142 | + |
| 143 | +None. |
| 144 | + |
| 145 | + |
| 146 | +How to Teach This |
| 147 | +================= |
| 148 | + |
| 149 | +All users can be taught that ``{/}`` is the new spelling for ``set()``, |
| 150 | +and that it is equivalent in all other ways. |
| 151 | +To help reinforce this, we will update the documentation to use ``{/}`` |
| 152 | +instead of ``set()``, including the tutorial, standard libary modules, |
| 153 | +and the Python Language Reference. |
| 154 | + |
| 155 | +For new users, sets can be introduced through syntax, noting that the four |
| 156 | +built-in collection types with syntax all have empty forms: |
| 157 | +``()``, ``[]``, ``{/}``, and ``{}``. |
| 158 | + |
| 159 | +The empty set uses a forwards slash to differentiate it from |
| 160 | +an empty dictionary. |
| 161 | +It uses this syntax because it looks like the mathematical symbol |
| 162 | +for the empty set (':math:`\emptyset`'). |
| 163 | +This can be used as a helpful mnemonic when teaching beginners, |
| 164 | +especially those that have a maths or science background. |
| 165 | + |
| 166 | + |
| 167 | +Reference Implementation |
| 168 | +======================== |
| 169 | + |
| 170 | +Forthcoming. |
| 171 | + |
| 172 | + |
| 173 | +Rejected Ideas |
| 174 | +============== |
| 175 | + |
| 176 | +Change ``{}`` to mean an empty set and use ``{:}`` for an empty dictionary |
| 177 | +-------------------------------------------------------------------------- |
| 178 | + |
| 179 | +This would be an entirely backwards incompatible change, |
| 180 | +all current empty :py:class:`dict` objects would become sets. |
| 181 | + |
| 182 | +Use a Unicode character (e.g. ``∅`` or ``ϕ``) |
| 183 | +--------------------------------------------- |
| 184 | + |
| 185 | +The Unicode character 'U+2205 ∅ EMPTY SET' is not currently a valid identifier. |
| 186 | +Introducing a Unicode character as syntax would be hard to use, |
| 187 | +as it does not appear on standard keyboards. |
| 188 | + |
| 189 | +Using other characters that look like ∅, such as 'U+03C6 ϕ GREEK SMALL LETTER |
| 190 | +PHI' or 'U+00D8 Ø LATIN CAPITAL LETTER O WITH STROKE', would be more confusing |
| 191 | +with the same drawbacks of using a Unicode character. |
| 192 | + |
| 193 | +Use the ``<>`` syntax |
| 194 | +--------------------- |
| 195 | + |
| 196 | +It does not have a resemblance to the syntax for non-empty sets. |
| 197 | +This would be harder to explain than this PEP's proposal. |
| 198 | + |
| 199 | +This syntax further has historic use as the inequality operator, |
| 200 | +which can still be accessed via ``from __future__ import barry_as_FLUFL``. |
| 201 | +Using both the ``barry_as_FLUFL`` future import and ``<>`` for the empty set |
| 202 | +would lead to parser ambiguity: what would ``<> <> <>`` mean? |
| 203 | + |
| 204 | +Use the ``s{}`` syntax |
| 205 | +---------------------- |
| 206 | + |
| 207 | +This syntax may cause confusion with ``s`` as a local variable. |
| 208 | +The only current use of prefixes of this kind is for string literals. |
| 209 | +This would be harder to explain than this PEP's proposal. |
| 210 | + |
| 211 | +Use the ``{*()}`` syntax |
| 212 | +------------------------ |
| 213 | + |
| 214 | +This relies on unpacking the empty tuple into a set, creating an empty set. |
| 215 | +This has the benefit of support since Python 3.5 (:pep:`448`), but is unwieldy |
| 216 | +and complicated to explain; it was not designed for this purpose. |
| 217 | + |
| 218 | +Use the ``{-}`` syntax |
| 219 | +---------------------- |
| 220 | + |
| 221 | +This syntax was originally proposed in :pep:`218`, |
| 222 | +but removed from the PEP before it was accepted. |
| 223 | +The authors prefer ``{/}`` due to the resemblance to :math:`\emptyset`. |
| 224 | + |
| 225 | +Use the ``{,}`` syntax |
| 226 | +---------------------- |
| 227 | + |
| 228 | +This is the authors' next preferred option. |
| 229 | +However, if a single comma were to be used to represent an empty collection, |
| 230 | +it may be confusing why this could not be used for empty tuples or lists. |
| 231 | +In time, there might be proposals to add support for ``[,]`` and ``(,)``. |
| 232 | +This conflicts with the general principle that |
| 233 | +'*there should be one-- and preferably only one --obvious way to do it*'. |
| 234 | +Having a visibly different form, in ``{/}``, helps to reinforce the idea |
| 235 | +that the syntax for the empty set is a special case, rather than a general rule |
| 236 | +for all empty collections. |
| 237 | + |
| 238 | + |
| 239 | +Open Issues |
| 240 | +=========== |
| 241 | + |
| 242 | +None. |
| 243 | + |
| 244 | + |
| 245 | +Acknowledgements |
| 246 | +================ |
| 247 | + |
| 248 | +* Chris Angelico, Dominykas Grigonis, Ben Hsing, James Webber, |
| 249 | + and other contributors to recent Discourse topics. |
| 250 | +* Hugo van Kemenade, for helpful feedback on a draft of the PEP. |
| 251 | + |
| 252 | + |
| 253 | +Footnotes |
| 254 | +========= |
| 255 | + |
| 256 | +.. _Discourse, August 2025 (#37): https://discuss.python.org/t/101197/37 |
| 257 | +.. _Discourse, August 2025: https://discuss.python.org/t/101197 |
| 258 | +.. _Discourse, December 2024: https://discuss.python.org/t/73235 |
| 259 | +.. _Discourse, March 2023: https://discuss.python.org/t/25213 |
| 260 | +.. _explicitly deferred: https://mail.python.org/pipermail/python-3000/2006-May/001599.html |
| 261 | +.. _python-3000, April 2006: https://mail.python.org/pipermail/python-3000/2006-April/001286.html |
| 262 | +.. _python-3000, May 2006: https://mail.python.org/pipermail/python-3000/2006-May/001666.html |
| 263 | +.. _ python-ideas, April 2021: https://mail.python.org/archives/list/[email protected]/message/X4TX2HDNKDJ7PVZL3DVI5QD2MIMRHKO4/ |
| 264 | +.. _ python-ideas, August 2020: https://mail.python.org/archives/list/[email protected]/message/QOBONXUPUMC3ULCGJU6FVHOCIZQDT45W/ |
| 265 | +.. _ python-ideas, January 2008: https://mail.python.org/archives/list/[email protected]/thread/IBMTTESRSF5755LNMVTUMHHABKOBSPUZ/#IBMTTESRSF5755LNMVTUMHHABKOBSPUZ |
| 266 | +.. _ python-ideas, June 2009: https://mail.python.org/archives/list/[email protected]/thread/AMWKPS54ZK6X2FI7NICDM6DG7LERIJFV/#AMWKPS54ZK6X2FI7NICDM6DG7LERIJFV |
| 267 | +.. _ python-ideas, November 2010: https://mail.python.org/archives/list/[email protected]/thread/N7CHDYXW2FYHDJ5BTP7CCC5HLAIINOVH/#N7CHDYXW2FYHDJ5BTP7CCC5HLAIINOVH |
| 268 | +.. _recent Discourse poll: https://discuss.python.org/t/101197/15 |
| 269 | + |
| 270 | + |
| 271 | +Copyright |
| 272 | +========= |
| 273 | + |
| 274 | +This document is placed in the public domain or under the |
| 275 | +CC0-1.0-Universal license, whichever is more permissive. |
0 commit comments