枚举导致类型不兼容的 mypy 错误
enumerate causes incompatible type mypy error
以下代码:
from typing import Union
def process(actions: Union[list[str], list[int]]) -> None:
for pos, action in enumerate(actions):
act(action)
def act(action: Union[str, int]) -> None:
print(action)
生成 mypy 错误: Argument 1 to "act" has incompatible type "object"; expected "Union[str, int]"
然而,当删除枚举函数时,输入没问题:
from typing import Union
def process(actions: Union[list[str], list[int]]) -> None:
for action in actions:
act(action)
def act(action: Union[str, int]) -> None:
print(action)
有谁知道枚举函数正在做什么来影响类型?
这是 python 3.9 和 mypy 0.921
我不知道它是如何影响类型的。我知道使用 len() 可以以相同的方式工作。它速度较慢,但如果它解决了问题,那可能是值得的。抱歉帮不上什么忙
似乎 mypy 无法推断类型并概括为对象。可能值得在他们身边提出一个问题。作为解决方法,您可以注释 'action'。这将消除错误。如果您从 typing
导入(遗留)List
是否有效?
enumerate.__next__
需要比 return 类型比 Tuple[int, Any]
更具体的可用上下文,所以我相信 mypy
本身需要修改才能使enumerate(actions)
产生 Tuple[int,Union[str,int]]
个值的推论。
在此之前,您可以显式转换 action
的值,然后再将其传递给 act
。
from typing import Union, cast
StrOrInt = Union[str, int]
def process(actions: Union[list[str], list[int]]) -> None:
for pos, action in enumerate(actions):
act(cast(StrOrInt, action))
def act(action: Union[str, int]) -> None:
print(action)
您还可以使 process
通用(现在我想到了,这可能是一个更好的主意,因为它避免了在运行时调用 cast
的开销)。
from typing import Union, cast, Iterable, TypeVar
T = TypeVar("T", str, int)
def process(actions: Iterable[T]) -> None:
for pos, action in enumerate(actions):
act(action)
def act(action: T) -> None:
print(action)
这里,T
不是类型的联合,而是一个单一的具体类型,其标识由对 process
的调用确定。 Iterable[T]
是 Iterable[str]
或 Iterable[int]
,具体取决于您传递给 process
的类型。这为 process
的其余调用修复了 T
,每次对 act
的调用都必须采用相同类型的参数。
Iterable[str]
或 Iterable[int]
是一个有效参数,在过程中将 T
绑定到 int
或 str
。现在 enumerate.__next__
显然 可以 有特定的 return 类型 Tuple[int, T]
.
以下代码:
from typing import Union
def process(actions: Union[list[str], list[int]]) -> None:
for pos, action in enumerate(actions):
act(action)
def act(action: Union[str, int]) -> None:
print(action)
生成 mypy 错误: Argument 1 to "act" has incompatible type "object"; expected "Union[str, int]"
然而,当删除枚举函数时,输入没问题:
from typing import Union
def process(actions: Union[list[str], list[int]]) -> None:
for action in actions:
act(action)
def act(action: Union[str, int]) -> None:
print(action)
有谁知道枚举函数正在做什么来影响类型? 这是 python 3.9 和 mypy 0.921
我不知道它是如何影响类型的。我知道使用 len() 可以以相同的方式工作。它速度较慢,但如果它解决了问题,那可能是值得的。抱歉帮不上什么忙
似乎 mypy 无法推断类型并概括为对象。可能值得在他们身边提出一个问题。作为解决方法,您可以注释 'action'。这将消除错误。如果您从 typing
导入(遗留)List
是否有效?
enumerate.__next__
需要比 return 类型比 Tuple[int, Any]
更具体的可用上下文,所以我相信 mypy
本身需要修改才能使enumerate(actions)
产生 Tuple[int,Union[str,int]]
个值的推论。
在此之前,您可以显式转换 action
的值,然后再将其传递给 act
。
from typing import Union, cast
StrOrInt = Union[str, int]
def process(actions: Union[list[str], list[int]]) -> None:
for pos, action in enumerate(actions):
act(cast(StrOrInt, action))
def act(action: Union[str, int]) -> None:
print(action)
您还可以使 process
通用(现在我想到了,这可能是一个更好的主意,因为它避免了在运行时调用 cast
的开销)。
from typing import Union, cast, Iterable, TypeVar
T = TypeVar("T", str, int)
def process(actions: Iterable[T]) -> None:
for pos, action in enumerate(actions):
act(action)
def act(action: T) -> None:
print(action)
这里,T
不是类型的联合,而是一个单一的具体类型,其标识由对 process
的调用确定。 Iterable[T]
是 Iterable[str]
或 Iterable[int]
,具体取决于您传递给 process
的类型。这为 process
的其余调用修复了 T
,每次对 act
的调用都必须采用相同类型的参数。
Iterable[str]
或 Iterable[int]
是一个有效参数,在过程中将 T
绑定到 int
或 str
。现在 enumerate.__next__
显然 可以 有特定的 return 类型 Tuple[int, T]
.