If we drop the requirement for pickle round-tripping then I would add a requirement that sentinel is unpicklable, to prevent accidents.
On Fri, May 14, 2021 at 8:38 PM Tal Einat firstname.lastname@example.org wrote:
I'll try to organize my thoughts a bit here. This is a bit long, welcome to skip to the final sentence for the "tl;dr".
Features one may want for a sentinel:
- Unique from other objects
- Globally unique, i.e. unique from other such sentinels (no consensus
here) 3. Clear repr (the original subject of this thread) - significant since these often appear in function signatures 4. Survives pickling round-trip (I brought this up since I was bitten by this once, but others have mentioned that this is usually irrelevant) 5. Can be given a clear type signature (this was brought up on twitter) - significant since without this nobody can add full type signatures even if they want to
The common `SENTINEL = object()` idiom fails #3, #4 and #5. This is what I've been using for years, and I now think that it isn't good enough. This not having a nice repr is what started this thread.
I'd also personally prefer something simple, ideally without a new class or module.
There are several simple idioms using existing features that seem like good options, so let's review those:
- Ellipsis, a.k.a. `...`. This has all of the features outlined above
except #2. My main issue with using Ellipsis for this is that it could be surprising and confusing for devs first encountering such use, and could be relatively awkward to figure out.
- An instance of a one-off class. dataclasses.MISSING is an example
of this. It is defined thus:
class _MISSING: pass MISSING = _MISSING()
Besides failing #4 (surviving pickle round-trips), its repr isn't great: <dataclasses._MISSING object at 0x7fe14b1e2e80>. That is easily overcome by implementing __repr__.
- A one-off class:
class MISSING: pass
This has all of the above features except #5: having a clear type signature (since its type is type). Using a class as a value this way could be surprising, though. It's repr also isn't great: <class 'dataclasses._MISSING'>.
- A value of an single-valued enum, for example (from ):
class _UNSET(enum.Enum): token = enum.auto()
This has all of the features above and is simple, just requiring a comment to explain what it is. It's repr is a bit awkward though:
All of these are in use by some developers, though not necessarily in the stdlib. None is perfect, though all are probably good enough. Since pickling is likely not relevant in most cases, I'm currently in favor of #2 making sure to implement a nice __repr__.
 https://twitter.com/nolar/status/1392962447166877697 _______________________________________________ Python-Dev mailing list -- email@example.com To unsubscribe send an email to firstname.lastname@example.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://email@example.com/message/BYLTDD72... Code of Conduct: http://python.org/psf/codeofconduct/