Skip to main content
typing.Final is a special typing construct introduced in Python 3.8 (PEP 591) used to indicate to static type checkers that a variable, class attribute, or module-level constant cannot be reassigned, redefined, or overridden. It enforces the immutability of a reference at the static analysis level.

Syntax and Parameterization

Final can be used with or without an explicit inner type. If the inner type is omitted, the static type checker infers the type strictly from the assigned value.

Core Rules and Constraints

  1. Initialization Requirement: Module-level constants and local variables must be initialized in the same statement where they are declared. For instance attributes, PEP 591 explicitly supports two patterns: declaring the Final attribute at the class level without an initializer and assigning it exactly once in __init__, or annotating the attribute directly inline within the __init__ method.
  2. Function Argument Prohibition: Final cannot be used in function or method argument annotations. Developers coming from languages with const or final parameters cannot replicate that behavior using Final in Python; attempting to do so results in a static type error.
  3. Reassignment Prohibition: Once assigned, any subsequent assignment to the same name in the same scope will trigger a static type checking error.
  4. Override Prohibition: Subclasses are forbidden from overriding class or instance attributes that were marked as Final in the parent class.
  5. Collection Mutability: Final only protects the binding of the name. If a Final variable points to a mutable object (like a list or dict), the internal state of that object can still be mutated.

The @final Decorator

While Final is used for variables and attributes, the typing module provides a complementary @final decorator for classes and methods.
  • Classes: When applied to a class, it indicates that the class cannot be subclassed.
  • Methods: When applied to a method, it indicates that the method cannot be overridden by any subclasses.

Runtime Behavior

Python does not enforce Final or @final constraints at runtime; enforcement relies entirely on static analysis tools such as mypy, pyright, or IDE language servers. Reassigning a Final variable or subclassing a @final class will execute successfully without raising runtime exceptions. However, there is a distinction in how the interpreter processes them:
  • Final (Type Hint): While Python does not enforce type hints at runtime, it does evaluate module-level and class-level variable annotations. These are stored in the __annotations__ dictionary of the respective module or class, actively altering the runtime state and allowing programmatic inspection. Annotations are only discarded for local variables inside functions.
  • @final (Decorator): The decorator is a standard function executed at runtime. It actively modifies the decorated class or method by setting a __final__ attribute to True on the object. While the interpreter does not use this attribute to block subclassing or overriding, the attribute exists in the runtime namespace and can be inspected programmatically.
Tired of Poor Python Skills? Fix That With Deep Grasping!Learn More