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
a sentinel value in most cases. However, sometimes an alternative sentinel
value is needed, usually when it needs to be distinct from ``None``. These
cases are common enough that several idioms for implementing such sentinels
have arisen over the years, but uncommon enough that there hasn't been a
clear need for standardization. However, the common implementations,
including some in the stdlib, suffer from several significant drawbacks.
value is needed, usually when it needs to be distinct from ``None`` since
``None`` is a valid value in that context. Such cases are common enough that
several idioms for implementing such sentinels have arisen over the years, but
uncommon enough that there hasn't been a clear need for standardization.
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
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
in the discussion:
1. Not having a distinct type, hence it being impossible to define clear
type signatures for functions with sentinels as default values
2. Incorrect behavior after being copied or unpickled, due to a separate
instance being created and thus comparisons using ``is`` failing
1. Some do not have a distinct type, hence it is impossible to define clear
type signatures for functions with such sentinels as default values.
2. They behave unexpectedly after being copied or unpickled, due to a separate
instance being created and thus comparisons using ``is`` failing.
In the ensuing discussion, Victor Stinner supplied a list of currently used
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
implementation method is needed or desirable, whether the drawbacks mentioned
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
improvement, but that focused on only a single problematic aspect of a few
cases, and failed to gather any support.
of this PEP created an issue on bugs.python.org (now a GitHub issue [3]_)
suggesting options for improvement, but that focused on only a single
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
the community's opinions. The poll's results were not conclusive, with 40%
voting for "The status-quo is fine / theres no need for consistency in
this", but most voters voting for one or more standardized solutions.
the community's opinions. After nearly two weeks, significant further,
discussion, and 39 votes, the poll's results were not conclusive. 40% had
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
sentinel factory / class / meta-class, also made publicly available in the
stdlib".
@ -142,8 +144,8 @@ Specification
A new ``Sentinel`` class will be added to a new ``sentinels`` module.
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
name of its module::
sentinel object, and three optional arguments: the repr of the object, its
boolean value, and the name of its module::
>>> from sentinels import Sentinel
>>> 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
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:``.
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
``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
``namedtuple``. For more details, see :pep:`435`.
The ``Sentinel`` class may be sub-classed. Instances of each sub-class will
be unique, even if using the same name and module. This allows for
customizing the behavior of sentinels, such as controlling their truthiness.
The ``Sentinel`` class may not be sub-classed, to avoid overly-clever uses
based on it, such as attempts to use it as a base for implementing singletons.
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
@ -359,7 +366,22 @@ Additional Notes
identical. If distinct sentinel objects are needed, make sure to use
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.
@ -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/>`_
.. [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/>`_
.. [5] `The "sentinels" package on PyPI <https://pypi.org/project/sentinels/>`_
.. [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>`_
.. [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