PEP 661: Small changes, clarifications and better wording (towards submission) (#4046)

This commit is contained in:
Tal Einat 2024-10-11 23:05:56 +03:00 committed by GitHub
parent 7d83e6c8f0
commit 5e6746e905
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 47 additions and 24 deletions

View File

@ -33,11 +33,12 @@ programming. They have many uses, such as for:
Python has the special value ``None``, which is intended to be used as such Python has the special value ``None``, which is intended to be used as such
a sentinel value in most cases. However, sometimes an alternative sentinel a sentinel value in most cases. However, sometimes an alternative sentinel
value is needed, usually when it needs to be distinct from ``None``. These value is needed, usually when it needs to be distinct from ``None`` since
cases are common enough that several idioms for implementing such sentinels ``None`` is a valid value in that context. Such cases are common enough that
have arisen over the years, but uncommon enough that there hasn't been a several idioms for implementing such sentinels have arisen over the years, but
clear need for standardization. However, the common implementations, uncommon enough that there hasn't been a clear need for standardization.
including some in the stdlib, suffer from several significant drawbacks. However, the common implementations, including some in the stdlib, suffer from
several significant drawbacks.
This PEP proposes adding a utility for defining sentinel values, to be used This PEP proposes adding a utility for defining sentinel values, to be used
in the stdlib and made publicly available as part of the stdlib. in the stdlib and made publicly available as part of the stdlib.
@ -70,10 +71,10 @@ function's signature to be overly long and hard to read::
Additionally, two other drawbacks of many existing sentinels were brought up Additionally, two other drawbacks of many existing sentinels were brought up
in the discussion: in the discussion:
1. Not having a distinct type, hence it being impossible to define clear 1. Some do not have a distinct type, hence it is impossible to define clear
type signatures for functions with sentinels as default values type signatures for functions with such sentinels as default values.
2. Incorrect behavior after being copied or unpickled, due to a separate 2. They behave unexpectedly after being copied or unpickled, due to a separate
instance being created and thus comparisons using ``is`` failing instance being created and thus comparisons using ``is`` failing.
In the ensuing discussion, Victor Stinner supplied a list of currently used In the ensuing discussion, Victor Stinner supplied a list of currently used
sentinel values in the Python standard library [2]_. This showed that the sentinel values in the Python standard library [2]_. This showed that the
@ -84,14 +85,15 @@ least one of the three above drawbacks.
The discussion did not lead to any clear consensus on whether a standard The discussion did not lead to any clear consensus on whether a standard
implementation method is needed or desirable, whether the drawbacks mentioned implementation method is needed or desirable, whether the drawbacks mentioned
are significant, nor which kind of implementation would be good. The author are significant, nor which kind of implementation would be good. The author
of this PEP created an issue on bugs.python.org [3]_ suggesting options for of this PEP created an issue on bugs.python.org (now a GitHub issue [3]_)
improvement, but that focused on only a single problematic aspect of a few suggesting options for improvement, but that focused on only a single
cases, and failed to gather any support. problematic aspect of a few cases, and failed to gather any support.
A poll [4]_ was created on discuss.python.org to get a clearer sense of A poll [4]_ was created on discuss.python.org to get a clearer sense of
the community's opinions. The poll's results were not conclusive, with 40% the community's opinions. After nearly two weeks, significant further,
voting for "The status-quo is fine / theres no need for consistency in discussion, and 39 votes, the poll's results were not conclusive. 40% had
this", but most voters voting for one or more standardized solutions. voted for "The status-quo is fine / theres no need for consistency in
this", but most voters had voted for one or more standardized solutions.
Specifically, 37% of the voters chose "Consistent use of a new, dedicated Specifically, 37% of the voters chose "Consistent use of a new, dedicated
sentinel factory / class / meta-class, also made publicly available in the sentinel factory / class / meta-class, also made publicly available in the
stdlib". stdlib".
@ -142,8 +144,8 @@ Specification
A new ``Sentinel`` class will be added to a new ``sentinels`` module. A new ``Sentinel`` class will be added to a new ``sentinels`` module.
Its initializer will accept a single required argument, the name of the Its initializer will accept a single required argument, the name of the
sentinel object, and two optional arguments: the repr of the object, and the sentinel object, and three optional arguments: the repr of the object, its
name of its module:: boolean value, and the name of its module::
>>> from sentinels import Sentinel >>> from sentinels import Sentinel
>>> NotGiven = Sentinel('NotGiven') >>> NotGiven = Sentinel('NotGiven')
@ -160,7 +162,9 @@ operator, as is recommended for ``None``. Equality checks using ``==`` will
also work as expected, returning ``True`` only when the object is compared also work as expected, returning ``True`` only when the object is compared
with itself. Identity checks such as ``if value is MISSING:`` should usually with itself. Identity checks such as ``if value is MISSING:`` should usually
be used rather than boolean checks such as ``if value:`` or ``if not value:``. be used rather than boolean checks such as ``if value:`` or ``if not value:``.
Sentinel instances are truthy by default, unlike ``None``.
Sentinel instances are truthy by default, unlike ``None``. This parallels the
default for arbitrary classes, as well as the boolean value of ``Ellipsis``.
The names of sentinels are unique within each module. When calling The names of sentinels are unique within each module. When calling
``Sentinel()`` in a module where a sentinel with that name was already ``Sentinel()`` in a module where a sentinel with that name was already
@ -183,9 +187,12 @@ automatic recognition does not work as intended, such as perhaps when using
Jython or IronPython. This parallels the designs of ``Enum`` and Jython or IronPython. This parallels the designs of ``Enum`` and
``namedtuple``. For more details, see :pep:`435`. ``namedtuple``. For more details, see :pep:`435`.
The ``Sentinel`` class may be sub-classed. Instances of each sub-class will The ``Sentinel`` class may not be sub-classed, to avoid overly-clever uses
be unique, even if using the same name and module. This allows for based on it, such as attempts to use it as a base for implementing singletons.
customizing the behavior of sentinels, such as controlling their truthiness. It is considered important that the addition of Sentinel to the stdlib should
add minimal complexity.
Ordering comparisons are undefined for sentinel objects.
Reference Implementation Reference Implementation
@ -359,7 +366,22 @@ Additional Notes
identical. If distinct sentinel objects are needed, make sure to use identical. If distinct sentinel objects are needed, make sure to use
distinct names. distinct names.
* There was a discussion on the typing-sig mailing list [8]_ about the typing * There is no single desirable value for the "truthiness" of sentinels, i.e.
their boolean value. It is sometimes useful for the boolean value to be
``True``, and sometimes ``False``. Of the built-in sentinels in Python,
``None`` evaluates to ``False``, while ``Ellipsis`` (a.k.a. ``...``)
evaluates to ``True``. The desire for this to be set as needed came up in
discussions as well.
* The boolean value of ``NotImplemented`` is ``True``, but using this is
deprecated since Python 3.9 (doing so generates a deprecation warning.)
This deprecation is due to issues specific to ``NotImplemented``, as
described in bpo-35712 [8]_.
* To define multiple, related sentinel values, possibly with a defined
ordering among them, one should instead use ``Enum`` or something similar.
* There was a discussion on the typing-sig mailing list [9]_ about the typing
for these sentinels, where different options were discussed. for these sentinels, where different options were discussed.
@ -368,12 +390,13 @@ References
.. [1] Python-Dev mailing list: `The repr of a sentinel <https://mail.python.org/archives/list/python-dev@python.org/thread/ZLVPD2OISI7M4POMTR2FCQTE6TPMPTO3/>`_ .. [1] Python-Dev mailing list: `The repr of a sentinel <https://mail.python.org/archives/list/python-dev@python.org/thread/ZLVPD2OISI7M4POMTR2FCQTE6TPMPTO3/>`_
.. [2] Python-Dev mailing list: `"The stdlib contains tons of sentinels" <https://mail.python.org/archives/list/python-dev@python.org/message/JBYXQH3NV3YBF7P2HLHB5CD6V3GVTY55/>`_ .. [2] Python-Dev mailing list: `"The stdlib contains tons of sentinels" <https://mail.python.org/archives/list/python-dev@python.org/message/JBYXQH3NV3YBF7P2HLHB5CD6V3GVTY55/>`_
.. [3] `bpo-44123: Make function parameter sentinel values true singletons <https://bugs.python.org/issue44123>`_ .. [3] `bpo-44123: Make function parameter sentinel values true singletons <https://github.com/python/cpython/issues/88289>`_
.. [4] discuss.python.org Poll: `Sentinel Values in the Stdlib <https://discuss.python.org/t/sentinel-values-in-the-stdlib/8810/>`_ .. [4] discuss.python.org Poll: `Sentinel Values in the Stdlib <https://discuss.python.org/t/sentinel-values-in-the-stdlib/8810/>`_
.. [5] `The "sentinels" package on PyPI <https://pypi.org/project/sentinels/>`_ .. [5] `The "sentinels" package on PyPI <https://pypi.org/project/sentinels/>`_
.. [6] `The "sentinel" package on PyPI <https://pypi.org/project/sentinel/>`_ .. [6] `The "sentinel" package on PyPI <https://pypi.org/project/sentinel/>`_
.. [7] `Reference implementation at the taleinat/python-stdlib-sentinels GitHub repo <https://github.com/taleinat/python-stdlib-sentinels>`_ .. [7] `Reference implementation at the taleinat/python-stdlib-sentinels GitHub repo <https://github.com/taleinat/python-stdlib-sentinels>`_
.. [8] `Discussion thread about type signatures for these sentinels on the typing-sig mailing list <https://mail.python.org/archives/list/typing-sig@python.org/thread/NDEJ7UCDPINP634GXWDARVMTGDVSNBKV/#LVCPTY26JQJW7NKGKGAZXHQKWVW7GOGL>`_ .. [8] `bpo-35712: Make NotImplemented unusable in boolean context <https://github.com/python/cpython/issues/79893>`_
.. [9] `Discussion thread about type signatures for these sentinels on the typing-sig mailing list <https://mail.python.org/archives/list/typing-sig@python.org/thread/NDEJ7UCDPINP634GXWDARVMTGDVSNBKV/#LVCPTY26JQJW7NKGKGAZXHQKWVW7GOGL>`_
Copyright Copyright