我的脚有问题。Mypy在函数定义中不使用窄类型。我有以下代码:
from typing import Callable
def foo(a: str | int) -> list[str]:
x: list[str] = ["abc", "def"]
if isinstance(a, int):
x.insert(a, "ghi")
elif isinstance(a, str):
x.insert(0, a)
return x
def bar(a: str | int) -> Callable[[list[str]], list[str]]:
if isinstance(a, int):
def modify(x: list[str]) -> list[str]:
x.insert(a, "ghi")
return x
elif isinstance(a, str):
def modify(x: list[str]) -> list[str]:
x.insert(0, a)
return x
return modify
foo
被正确地识别为良型。我认为bar
也应该是类型良好的,但是mymyy给出了这个错误:
16: error: Argument 1 to "insert" of "list" has incompatible type "Union[str, int]"; expected "SupportsIndex"
20: error: Argument 2 to "insert" of "list" has incompatible type "Union[str, int]"; expected "str"
这是我的错误吗?我能不能用别的方式输入这个程序?
与其他类型检查器比较表明这是特定于我的。Pyright在这里没有抱怨什么,但是如果x.insert(0, a)
被x.insert(a, "ghi")
取代了,他会抱怨的。
我怀疑这是因为嵌套函数定义使名称解析和类型窄化变得相当复杂。您可以通过将a
重新分配给类型良好的变量,然后在每个分支中使用modify
关闭它来修复它:
from typing import Callable
def bar(a: str | int) -> Callable[[list[str]], list[str]]:
if isinstance(a, int):
# create a new variable with the correct type while mypy
# can keep track of what's going on
idx: int = a
def modify(x: list[str]) -> list[str]:
# close over the new variable instead of `a`
x.insert(idx, "ghi")
return x
elif isinstance(a, str):
# do the same thing here
# the explicit type annotation isn't even actually necessary
# I just put it for clarity
s: str = a
def modify(x: list[str]) -> list[str]:
x.insert(0, s)
return x
return modify