Instance and class attributes
Mypy detects if you try to access a missing attribute. For this to work correctly, instance and class attributes must be defined or initialized within the class:This is similar to each class having an implicitly defined
__slots__ attribute. This is only enforced during type checking, not at runtime.Explicit attribute annotations
You can declare types of variables in the class body explicitly:Annotating __init__ methods
The __init__ method is special — it doesn’t return a value. This is best expressed as -> None:
If
__init__ has no annotated arguments and no return type annotation, it is considered an untyped method and its body is not type checked.Class attribute annotations
UseClassVar[T] to explicitly declare that an attribute should not be set on instances:
An attribute without
ClassVar annotation can be used as both a class and instance variable.Overriding methods
When overriding a statically typed method, mypy checks that the override has a compatible signature:You can vary return types covariantly and argument types contravariantly in overriding methods.
The @override decorator
You can explicitly mark a method as overriding a base method using @override:
Abstract base classes
Mypy supports Python abstract base classes (ABCs). UseABCMeta metaclass and @abstractmethod decorator:
Implicit abstract classes
A class that inherits an abstract method but doesn’t implement it is implicitly abstract:Slots
When a class has explicitly defined__slots__, mypy checks that all attributes assigned to are members of __slots__:
__slots__ when:
- All base classes (except builtin ones) have explicit
__slots__defined __slots__does not include__dict__- All values in
__slots__are string literals
Best practices
Always declare instance attributes
Always declare instance attributes
Either initialize them in
__init__ or declare them in the class body with type annotations.Use ClassVar for class-level constants
Use ClassVar for class-level constants
This prevents accidental modification through instances and makes your intent clear.
Use @override for clarity
Use @override for clarity
Explicitly marking overridden methods helps catch errors when base methods are renamed.
Prefer ABCs for interfaces
Prefer ABCs for interfaces
Abstract base classes make your interfaces explicit and help catch missing implementations.