There was a discussion a while back ( a year or so?? ) on Python-ideas that introduced the idea of having more "sentinel-like" singletons in Python -- right now, we only have None. 

I can't remember the context, but the consensus seemed to be that it was easy to create a custom sentinel object, and it was not worth adding more "official" ones to the language. But this conversation reminded me about that, and while I do agree that we don't need more that are elevated to the status of None, maybe it would be good to have a couple (or only MISSING) in the standard library somewhere "central" for everyone to use. "central" rather than in, say, dataclasses. 

I'm not sure where that should be, the operator module, maybe??

Ayway, if someone were to put one of the nifty implementations being discussed here in the stdlib --I'd use it :-)

-CHB


 

On Thu, May 13, 2021 at 1:14 PM Tal Einat <taleinat@gmail.com> wrote:
On Thu, May 13, 2021 at 8:46 PM Eric V. Smith <eric@trueblade.com> wrote:
>
>
> On 5/13/2021 1:39 PM, Tal Einat wrote:
> > Here is my suggestion (also posted on the related bpo-44123), which is
> > also simple, ensures a single instance is used, even considering
> > multi-threading and pickling, and has a better repr:
> >
> > class Sentinel:
> >      def __new__(cls, *args, **kwargs):
> >          raise TypeError(f'{cls.__qualname__} cannot be instantiated')
> >
> > class MISSING(Sentinel):
> >      pass
>
>  >>> MISSING
> <class '__main__.MISSING'>
>
> I think a repr of just "MISSING", or maybe "dataclasses.MISSING" would
> be better.

The repr uses whatever module the class is defined in, so we'd get:

>>> from dataclasses import MISSING
>>> MISSING
<class 'dataclasses.MISSING'>

We could override that to something even cleaner with a meta-class. For example:

class Sentinel(type):
    @classmethod
    def __prepare__(cls, name, bases, **kwds):
        d = super().__prepare__(name, bases, **kwds)
        def __new__(cls_, *args, **kwargs):
            raise TypeError(f'{cls_!r} is a sentinel and cannot be
instantiated')
        d.update(__new__=__new__)
        return d

    def __repr__(cls):
        return f'{cls.__module__}.{cls.__qualname__}'

Which results in:

>>> from dataclasses import MISSING
>>> MISSING
dataclasses.MISSING
>>> type(MISSING)
<class 'sentinels.Sentinel'>
>>> MISSING()
Traceback (most recent call last): ...
TypeError: dataclasses.MISSING is a sentinel and cannot be instantiated

- Tal


- Tal
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/ECYFQWPBQPRN4ZKDU6WNPPAG3Y5XZ2BD/
Code of Conduct: http://python.org/psf/codeofconduct/


--
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython