Python Type Hints - Mypy doesn’t allow variables to change type2021-05-23
Mypy does not allow variables to change type. I found this a little bit of a shock at first, but after I adapted, I found my code was more readable.
For example, take this snippet of a Django view I tried to write in DB Buddy:
The code fetches the
size query parameter, which is a string, and tries to parse it as an
int, or fall back to the default value
Python can run this code just fine, but if we check it with Mypy, we’ll see some errors:
We might try to fix the errors by explicitly declaring that
size is changing type:
…but Mypy does not allow redefinition:
We might also try declaring
size with the union of types it takes,
This can work in some cases, but not generally.
Mypy can use type narrowing to figure out when
size must be an
int, but this isn’t always possible.
In other cases we will have to use type narrowing or
cast() to tell Mypy we know the type is
int after the parsing, to allow
Such function calls are unnecessary noise in our code.
The best solution is to use two variables, the first a
str and the second an
This makes Mypy pass:
This may seem like a bit more work, but it clarifies the code, for both Mypy and human readers.
When we see the name
size later in the function, we know it’s an
int from its first mention, and don’t have to follow a “type lifecycle” through the function.
(Note: there is a configuration value called
allow_redefinition that allows type redefinition in some contexts.
But I wouldn’t recommend turning it on.
It doesn’t help in the example here anyway.)
May type hints clarify your code,
Want better tests? Check out my book Speed Up Your Django Tests which teaches you to write faster, more accurate tests.
One summary email a week, no spam, I pinky promise.
- Python Type Hints - How to Upgrade Syntax with pyupgrade
- Python Type Hints - What’s the point of NoReturn?
- Python Type Hints - How to use Mypy’s unreachable code detection
Tags: mypy, python
© 2021 All rights reserved.