Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

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.
from typing import Final


# Unparameterized (Type inferred as int)
TIMEOUT: Final = 10


# Parameterized (Explicitly typed as float)
MAX_LATENCY: Final[float] = 5.5

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.
from typing import Final

class Configuration:
    # Class attribute initialized immediately
    VERSION: Final[str] = "1.0.0"
    
    # Instance attribute declared at the class level
    config_id: Final[int]
    
    def __init__(self) -> None:
        # Instance attribute initialized exactly once in __init__
        self.config_id = 42
        
        # Instance attribute annotated directly inline
        self.max_retries: Final[int] = 3

class CustomConfiguration(Configuration):
    # ERROR: Cannot override a final attribute
    VERSION = "2.0.0" 


# ERROR: Cannot use Final for function arguments
def process(data: Final[list]) -> None:
    pass


# ERROR: Cannot reassign a final variable
TIMEOUT: Final = 10
TIMEOUT = 20 


# VALID: Mutating the internal state of a final object
SETTINGS: Final[list[str]] = ["auth", "logging"]
SETTINGS.append("metrics") 

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.
from typing import final

@final
class BaseCore:
    pass


# ERROR: Cannot inherit from a final class
class ExtendedCore(BaseCore): 
    pass

class DataProcessor:
    @final
    def process(self) -> None:
        pass

class ImageProcessor(DataProcessor):
    # ERROR: Cannot override a final method
    def process(self) -> None: 
        pass

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.
Master Python with Deep Grasping Methodology!Learn More