PEP 661: Sentinel Values

To help guide decision-making, I consider be able to use this for sentinels in the stdlib a major goal and a guiding principle. To that end, I’ve conducted an updated search of the stdlib today, reviewing @vstinner’s original list of sentinels in the stdlib and adding others. (Several have been removed since, see at the end of this post.) The following list also includes some information about each sentinel: how it is implemented, what it is used for, and why (to the extent that I could figure that out).

Of the 27 sentinels below:

  • 7 use a dedicated class, 5 of which have a custom repr; the other 20 use object()
  • All are “truthy” (evaluate to True in a boolean context).
  • About half are exposed externally and half are not.
  • Most are defined at the module level. A few are defined on every call to a function/method; of those about half do so intentionally for a clear reason.

List of sentinels:

  • _collections_abc.MutableMapping.__marker
    = object()
    Default value for the default argument of the .pop() method
    Needs to be distinct from other possible values such as None

  • annotationlib._sentinel
    = object()
    Default value for the type_params argument of ForwardRef._evaluate()
    Used to clearly deprecate not passing type_params

  • configparser: _UNSET
    = object()

  • configparser.UNNAMED_SECTION
    Uses a dedicated class with a custom repr: “<UNNAMED_SECTION>”
    Not a default function argument value: Intended for users to pass in to signify an unnamed section

  • dataclasses._ANY_MARKER
    = object()
    Not a default argument value: Used internally

  • dataclasses: _HAS_DEFAULT_FACTORY, MISSING, KW_ONLY
    A dedicated class for each, one with a custom repr

  • datetime.timezone._Omitted
    = object()
    Used internally to disallow None for the name argument to the timezone class

  • dis.UNKNOWN
    Uses a dedicated class with a custom repr: “”
    Not a default argument value: Used in output to signal something specific

  • functools.lru_cache: sentinel
    = object()
    Each lru_cache() call creates its own sentinel object
    Used for dict-like lookups

  • functools._initial_missing
    = object()
    Default function argument value for reduce()

  • functools._NOT_FOUND
    = object()
    Not a default argument value, used as default for cache.get()

  • glob._no_recurse_symlinks
    = object()
    Not a default argument value: Used internally
    Apparently used instead of something like None for better clarity

  • glob._walk_symlinks_as_files
    = object()
    Not a default argument value: Used internally
    Apparently used instead of something like None for better clarity

  • heapq: temporary sentinel in nsmallest() and nlargest()
    = object()
    Not a default argument value: used as default for min() or max()

  • inspect._is_coroutine_mark
    = object()
    Not a default argument value: used to be different from None when calling getattr()

  • pickle._NoValue
    = object()
    Not a default argument value: Used internally for various .get() and getattr() calls

  • plistlib._undefined
    = object()
    Not a default argument value: used for an internal list of objects while parsing

  • pydoc._GoInteractive
    = object()
    The default value for the request argument of Helper()
    Apparently used instead of something like None for better clarity

  • runpy._ModifiedArgv0._sentinel
    = object()
    Not a default argument value: used to mark whether a value has been initialized (“saved”)

  • sched: _sentinel
    = object()
    Default value for the kwargs argument of scheduler.enter() and scheduler.enterabs()
    Could be None, apparently used for better clarity

  • sentinel.comare(): sentinel
    = object(), redefined on each call
    Used as a default for getattr()

  • socket._GLOBAL_DEFAULT_TIMEOUT
    = object()
    The default value for the timeout argument of create_connection()
    Apparently used instead of something like None for better clarity

  • tarfile._KEEP
    = object()
    Apparently used instead of something like None for better clarity

  • traceback: _sentinel
    Uses a dedicated class with a custom repr: “”
    Default value for the value and tb arguments of print_exception()
    Could be None, apparently used for better clarity

  • traceback.BUILTIN_EXCEPTION_LIMIT
    = object()
    Internal, used to signal to StackSummary._extract_from_extended_frame_gen() that it is being used for Python’s internal exception handling.
    Apparently used instead of something like None for better clarity

  • programming.rst
    The example for optional argument defaults that could be None recommends using object(), which would result in bad function signatures.

Removed from the stdlib (of those in @vstinner’s original list):

  • cgitb.__UNDEF__
  • fnmatch.translate() STAR
  • inspect._signature_fromstr(): invalid
7 Likes