The Spectrum Dispatch News

technology

Python’s Six Pre‑declared Constants Behave Differently

The language treats True, False, None, __debug__, Ellipsis and NotImplemented as constants, but each has distinct rules regarding assignment, attribute access and built‑in mutation

Python’s Six Pre‑declared Constants Behave Differently

According to the source, Python defines six pre‑declared constants: True, False, None, debug, Ellipsis (written as …) and NotImplemented. True, False and None are keywords; they are lexical tokens rather than identifiers. Because they are resolved in the lexer, using them as attributes—for example x.True—produces a SyntaxError. The source notes that no other names in Python are treated this way during lexing. debug is different: it is a normal identifier whose value is True in a regular build and False when the interpreter is started with the -O optimization flag. Although it is an identifier, it cannot be assigned to; attempting debug = 67 or x.debug = 67 raises a SyntaxError. Reading debug as an attribute on an object that lacks that attribute raises AttributeError, while deleting the name with del debug also yields a SyntaxError, whereas deleting an attribute named debug follows the usual NameError or AttributeError path. The source points out that assigning to debug is one of a few cases where a SyntaxError is raised even though the syntax is otherwise valid; similar cases involve using yield or await outside a function. Ellipsis and NotImplemented are documented as constants but are actually regular built‑ins. Consequently they can be shadowed by assigning to the names Ellipsis or NotImplemented, as shown by the example NotImplemented = 67 after which the name evaluates to 67. However the literal token … remains bound to the original Ellipsis object, so evaluating … still yields the Ellipsis singleton despite the name being rebound. True, False and None also exist as entries in the builtins module. They can be retrieved via getattr(builtins, ‘True’) and similar calls. Using setattr to replace these entries—for instance setattr(builtins, ‘True’, 67)—changes the value returned by getattr but does not affect the lexical token: evaluating True still yields the original Boolean True. The same behaviour holds for debug: modifying builtins.debug leaves the name debug unchanged when accessed directly. The source therefore concludes that, although True, False, None and debug can be altered in the builtins dictionary, their values as language constants are insulated from such changes, whereas Ellipsis and the name Ellipsis are not similarly protected.

Python’s Six Pre‑declared Constants Behave Differently

Key facts

  • True, False, None are keywords and lexical tokens
  • debug is True normally, False with -O, cannot be assigned to
  • Ellipsis and NotImplemented are normal builtins that can be shadowed
  • Modifying builtins does not change the lexical token values of True, False, None or debug
  • Assigning to debug raises SyntaxError despite syntactically valid code

Sources

← All posts