PEP 661: Small changes, clarifications and better wording (towards submission) (#4046)
This commit is contained in:
parent
7d83e6c8f0
commit
5e6746e905
|
@ -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 / there’s 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 / there’s 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
|
||||
|
|
Loading…
Reference in New Issue