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
|
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 / there’s 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 / 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
|
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
|
||||||
|
|
Loading…
Reference in New Issue