First steps
Type system reference
Configuring and running mypy
Miscellaneous
Project Links
This section introduces these related features:
Final names are variables or attributes that should not be reassigned afterinitialization. They are useful for declaring constants.
Final methods should not be overridden in a subclass.
Final classes should not be subclassed.
All of these are only enforced by mypy, and only in annotated code.There is no runtime enforcement by the Python runtime.
Note
The examples in this page importFinal andfinal from thetyping module. These types were added totyping in Python 3.8,but are also available for use in Python 3.4 - 3.7 via thetyping_extensions package.
You can use thetyping.Final qualifier to indicate thata name or attribute should not be reassigned, redefined, oroverridden. This is often useful for module and class-levelconstants to prevent unintended modification. Mypy will preventfurther assignments to final names in type-checked code:
fromtypingimportFinalRATE:Final=3_000classBase:DEFAULT_ID:Final=0RATE=300# Error: can't assign to final attributeBase.DEFAULT_ID=1# Error: can't override a final attribute
Another use case for final attributes is to protect certain attributesfrom being overridden in a subclass:
fromtypingimportFinalclassWindow:BORDER_WIDTH:Final=2.5...classListView(Window):BORDER_WIDTH=3# Error: can't override a final attribute
You can use@property to make an attribute read-only, but unlikeFinal,it doesn’t work with module attributes, and it doesn’t prevent overriding insubclasses.
You can useFinal in one of these forms:
You can provide an explicit type using the syntaxFinal[<type>]. Example:
ID:Final[int]=1
Here, mypy will infer typeint forID.
You can omit the type:
ID:Final=1
Here, mypy will infer typeLiteral[1] forID. Note that unlike forgeneric classes, this isnot the same asFinal[Any].
In class bodies and stub files, you can omit the right-hand side and just writeID:Final[int].
Finally, you can writeself.id:Final=1 (also optionally witha type in square brackets). This is allowedonly in__init__ methods so the final instance attribute isassigned only once when an instance is created.
Final¶These are the two main rules for defining a final name:
There can beat most one final declaration per module or class fora given attribute. There can’t be separate class-level and instance-levelconstants with the same name.
There must beexactly one assignment to a final name.
A final attribute declared in a class body without an initializer mustbe initialized in the__init__ method (you can skip theinitializer in stub files):
classImmutablePoint:x:Final[int]y:Final[int]# Error: final attribute without an initializerdef__init__(self)->None:self.x=1# Good
Final can only be used as the outermost type in assignments or variableannotations. Using it in any other position is an error. In particular,Final can’t be used in annotations for function arguments:
x:list[Final[int]]=[]# Error!deffun(x:Final[list[int]])->None:# Error!...
Final andClassVar should not be used together. Mypy will inferthe scope of a final declaration automatically depending on whether it wasinitialized in the class body or in__init__.
A final attribute can’t be overridden by a subclass (even with anotherexplicit final declaration). Note, however, that a final attribute canoverride a read-only property:
classBase:@propertydefID(self)->int:...classDerived(Base):ID:Final=1# OK
Declaring a name as final only guarantees that the name will not be re-boundto another value. It doesn’t make the value immutable. You can use immutable ABCsand containers to prevent mutating such values:
x:Final=['a','b']x.append('c')# OKy:Final[Sequence[str]]=['a','b']y.append('x')# Error: Sequence is immutablez:Final=('a','b')# Also an option
Like with attributes, sometimes it is useful to protect a method fromoverriding. You can use thetyping.final decorator for this purpose:
fromtypingimportfinalclassBase:@finaldefcommon_name(self)->None:...classDerived(Base):defcommon_name(self)->None:# Error: cannot override a final method...
This@final decorator can be used with instance methods, class methods,static methods, and properties.
For overloaded methods, you should add@final on the implementationto make it final (or on the first overload in stubs):
fromtypingimportfinal,overloadclassBase:@overloaddefmethod(self)->None:...@overloaddefmethod(self,arg:int)->int:...@finaldefmethod(self,x=None):...
You can apply thetyping.final decorator to a class to indicateto mypy that it should not be subclassed:
fromtypingimportfinal@finalclassLeaf:...classMyLeaf(Leaf):# Error: Leaf can't be subclassed...
The decorator acts as a declaration for mypy (and as documentation forhumans), but it doesn’t actually prevent subclassing at runtime.
Here are some situations where using a final class may be useful:
A class wasn’t designed to be subclassed. Perhaps subclassing would notwork as expected, or subclassing would be error-prone.
Subclassing would make code harder to understand or maintain.For example, you may want to prevent unnecessarily tight coupling betweenbase classes and subclasses.
You want to retain the freedom to arbitrarily change the class implementationin the future, and these changes might break subclasses.
An abstract class that defines at least one abstract method orproperty and has@final decorator will generate an error frommypy since those attributes could never be implemented.
fromabcimportABCMeta,abstractmethodfromtypingimportfinal@finalclassA(metaclass=ABCMeta):# error: Final class A has abstract attributes "f"@abstractmethoddeff(self,x:int)->None:pass