Although I’ve been using Python 3.12 in production for nearly a year, one neat feature in
the typing module that escaped me was the @override
decorator. Proposed in PEP-6981,
it’s been hanging out in typing_extensions
for a while. This is one of those small
features you either don’t care about or get totally psyched over. I’m definitely in the
latter camp.
In languages like C#, Java, and Kotlin, explicit overriding is required. For instance, in
Java, you use @Override
to make it clear you’re overriding a method in a sub class. If you
mess up the method name or if the method doesn’t exist in the superclass, the compiler
throws an error. Now, with Python’s @override
decorator, we get similar benefits—though
only if you’re using a static type checker.
Here’s an example:
from typing import override
class Animal:
def sound(self) -> str:
return "Unknown"
class Cat(Animal):
@override
def soud(self) -> str: # Notice the typo: sound -> soud
# Your implementation here
return "Meow"
In this example, Cat
inherits from Animal
, and we intended to override the sound
method. But there’s a typo in the subclass method name. Running mypy
will flag it:
error: Method "soud" is marked as an override, but no base method was found
with this name [misc]
Found 1 error in 1 file (checked 1 source file)
This decorator also works with class, property, or any other methods. Observe:
from typing import override
class Animal:
@property
def species(self) -> str:
return "Unknown"
class Cat(Animal):
@override
@property
def species(self) -> str:
return "Catus"
If the overriding method isn’t marked with @property
, mypy
will raise an error:
error: Signature of "species" incompatible with supertype "Animal" [override]
note: Superclass:
note: str
note: Subclass:
note: def species(self) -> str
Found 1 error in 1 file (checked 1 source file)
The error message could be clearer here, though. You can use @override
with class methods
too:
from typing import override
class Animal:
@classmethod
def category(cls) -> str:
return "Unknown"
class Cat(Animal):
@override
@classmethod
def category(cls) -> str:
return "Mammal"
In these cases, the order of @override
doesn’t matter; you can put it before or after the
property
decorator, and it’ll still work. I personally prefer keeping it as the outermost
decorator.
I’ve been gradually adding the @override
decorator to my code, as it not only prevents
typos but also alerts me if an upstream method name changes.
Recent posts
- Injecting Pytest fixtures without cluttering test signatures
- Quicker startup with module-level __getattr__
- Docker mount revisited
- Topological sort
- Writing a circuit breaker in Go
- Discovering direnv
- Notes on building event-driven systems
- Bash namerefs for dynamic variable referencing
- Behind the blog
- Shell redirection syntax soup