Python @override Decorator in 3.12: Catch Bugs Early
Python 3.12 introduces the @override decorator from the typing module, letting static type checkers catch misspelled method names, accidental subclass methods, and parent class signature changes automatically.
Python's @override Decorator in 3.12: Finally Catching Bugs Before They Catch You
If you've ever spent an hour debugging why your subclass method isn't being called, only to realize you misspelled the method name, you're not alone. Python 3.12 finally gives us the @override decorator from the typing module, and it's exactly the safety net many of us have been waiting for.
What Does @override Actually Do?
The @override decorator tells Python's type checkers (like mypy or Pyright) that a method in a subclass is meant to override a method from its parent class. If you accidentally spell the method name wrong, or the parent class changes the method signature, the type checker will catch it.
Here's what it looks like in practice:
from typing import override
class Vehicle:
def start(self) -> None:
print("Vehicle starting...")
def stop(self) -> None:
print("Vehicle stopping...")
class Car(Vehicle):
@override
def start(self) -> None:
print("Car engine roaring to life!")
@override
def stopp(self) -> None:
print("Car stopping...")
With the @override decorator on stopp, your type checker would immediately flag a warning because stopp doesn't exist in the Vehicle class. Without it, Python would silently create a new method, and car.stop() would call the parent's version — likely not what you intended.
Why This Matters for Real Projects
At PythonSkillset, we've seen codebases where inheritance bugs waste hours of debugging time. The @override decorator prevents three common mistakes:
- Typos in method names (like
stoppinstead ofstop) - Accidental creation of new methods when you meant to override
- Parent class changes that break your subclass without you noticing
How to Use It Today
You don't need to wait for everyone to use Python 3.12. The decorator works with current type checkers, and it's completely optional at runtime — it doesn't affect how your code runs. You can start using it immediately.
from typing import override
class Logger:
def log(self, message: str) -> None:
print(f"[LOG] {message}")
class FileLogger(Logger):
@override
def log(self, message: str) -> None:
with open("log.txt", "a") as f:
f.write(f"{message}\n")
The Only Catch
The @override decorator only helps if you're using static type checking tools. At PythonSkillset, we recommend running mypy as part of your pre-commit hooks or CI pipeline. The runtime behavior stays exactly the same — no performance cost, no new errors thrown.
Should You Retrofit Old Code?
For new classes, absolutely use @override everywhere you mean to override. For existing code, add it gradually when you're modifying or debugging inheritance hierarchies. It's especially valuable for large frameworks and libraries where you subclass third-party classes.
The Python community has been asking for this feature for years, and it's a small change that makes a big difference in code quality. Give it a try on your next project — your future self will thank you when you catch that misspelled method name at review time instead of debugging it at 2 AM.
Comments
Questions, corrections, and tips stay visible for everyone reading this page.
Join the discussion
No comments yet
Be the first to leave a note — it helps the next reader.