Why does Mypy complain that it requires a type annotation for a list comprehension variable, when it is impossible to annotate such a variable using MyPy?
Specifically, how can I resolve the following error:
from enum import EnumMeta
def spam( y: EnumMeta ):
return [[x.value] for x in y] 🠜 Mypy: Need type annotation for 'x'
cast
doesn't work:
return [[cast(Enum, x).value] for x in y] 🠜 Mypy: Need type annotation for 'x'
Even though Mypy doesn't support annotations (x:Enum
) in such a case I see the usage of the variable can be annotated using cast
(see this post). However, cast(Enum, x)
doesn't stop Mypy complaining that the variable isn't annotated in the first place.
#type:
doesn't work:
return [[x.value] for x in y] # type: Enum 🠜 Mypy: Misplaced type annotation
I also see that a for
loop variable can be annotated using a comment, # type:
(see this post). However, # type: Enum
doesn't work for list comprehension's for
.
List comprehensions are useful and can help you write elegant code that's easy to read and debug, but they're not the right choice for all circumstances. They might make your code run more slowly or use more memory.
Mypy runs are slow If your mypy runs feel slow, you should probably use the mypy daemon, which can speed up incremental mypy runtimes by a factor of 10 or more. Remote caching can make cold mypy runs several times faster.
“Mypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or 'duck') typing and static typing. Mypy combines the expressive power and convenience of Python with a powerful type system and compile-time type checking.” A little background on the Mypy project.
It's not considered bad. are generally frowned upon. In other words, readability is important. Basically, if you're not storing the result, and/or it modifies some other object, then a list comprehension is probably a bad idea.
In a list comprehension, the iterator must be cast instead of the elements.
from typing import Iterable, cast
from enum import EnumMeta, Enum
def spam(y: EnumMeta):
return [[x.value] for x in cast(Iterable[Enum], y)]
This allows mypy
to infer the type of x
as well. In addition, at runtime it performs only 1 cast instead of n casts.
If spam
can digest any iterable that produces enums, it is easier to type hint this directly.
from typing import Iterable
from enum import Enum
def spam(y: Iterable[Enum]):
return [[x.value] for x in y]
MisterMyagi's answer is the best solution for this specific case. It may be worth noting, however, that it is also possible to declare the type of a variable before that variable is defined. The following also passes MyPy:
from enum import Enum
def spam(y: type[Enum]):
x: Enum
return [[x.value] for x in y]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With