PEP 661: Sentinel Values

To me the question is whether identity has to be kept on serialization.


If no, then mental model is very clear:

"It behaves in almost identical manner as object() except for __repr__ (and maybe customizable truth value).


If yes, then it is a bit of an issue as it either:
a) Adds a fair amount of complexity
b) Needs a different spec

As for (b), the simplest way to achieve it that I have found is:

class NULL(Sentinel):
    """Multiline doc for free"""
    # False / True / None (NotImplementedError)
    truth = True

# Sentinel is just convenience baseclass
class Sentinel(metaclass=SentinelMeta):
    pass

# Thus, it could alternatively be:
class NULL(metaclass=SentinelMeta):
    ...

I quite like it personally as it keeps things simple, offers all basic features including serialization identity retainment (when defined at module level) without “black magic” and implementation is 12 lines long.


So I use above in places where I was using object() before.

Serialization identity retainment allows it to be used for few more cases, but I am not sure if that is needed. If not, then the above is inferior to this PEP as class creation is much more costly than instantiation.


Thus, maybe it would be simpler to keep this in line with object() with few additional basic features:

  1. __repr__
  2. customizable truth value via truth arg (maybe)
  3. customizable __doc__ via doc argument (maybe)
  4. Shorthand Sentinel.NAME instantiation. (maybe)

And leave all complexities for a separate concept, which (among other benefits) would allow users to define Sentinels for global/framework wide usage. As per Singletonobject.c and unification of `singletons` and `singlenels` - #7 by Alex-Wasowicz

2 Likes