Python Type Hints - Use object instead of Any
When starting out with Python type hints, it’s common to overuse
typing.Any. This is dangerous, since
Any entirely disables type checking for a variable, allowing any operation.
If you’re using
Any to mean “this object could be any type, and I don’t care what”, you probably want to use
object instead. Every object in Python inherits from
object, which makes it an “opaque” type that only allows operations common to everything. Therefore we could pass, print, or store such variables in a container, but we couldn’t do anything more specific.
Take these few lines of code:
from typing import Any x: Any = 123 x.does_not_exist()
We assign an
x, which we marked explicitly as having type
Any. The next line has an operation that will fail, since
ints do not have a
does_not_exist() method. But, due to the
Any type, Mypy does not detect the failure:
$ mypy example.py Success: no issues found in 1 source file
If we didn’t care what type
x contained, we would be better off typing it as
x: object = 123 x.does_not_exist()
Mypy can then correctly detect the bug:
$ mypy example.py example.py:2: error: "object" has no attribute "does_not_exist" [attr-defined] Found 1 error in 1 file (checked 1 source file)
Another example where
Any can be overused is when passing through
from typing import Any from example import Widget class BlueWidget(Widget): def __init__(self, *args: Any, blueness: int = 50, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.blueness = blueness
Since we are only passing on
kwargs, the use of
Any doesn’t really have an effect. But if the code ever evolves to look inside
kwargs, for example to log them, then such operations will not be type checked.
We should instead use
object to declare that we don’t know or care about the types of the values in
from example import Widget class BlueWidget(Widget): def __init__(self, *args: object, blueness: int = 50, **kwargs: object) -> None: super().__init__(*args, **kwargs) self.blueness = blueness
object is also less work since we don’t have to import it!
Improve your Django develompent experience with my new book.
One summary email a week, no spam, I pinky promise.
- Python Type Hints - *args and **kwargs
- Python Type Hints - How to Use TypedDict
- Python Type Hints - How to Fix Circular Imports
Tags: mypy, python