Mypy报告两个相同的打字法不兼容



我使用ParamSpecConcatenate来键入提示可调用项。

这是代码

from collections.abc import Callable
from typing import Concatenate, Generic, ParamSpec, TypeVar
T0 = TypeVar("T0")
P1 = ParamSpec("P1")
T1 = TypeVar("T1")

class TestClass(Generic[T0]):
def __init__(self, obj: T0, method: Callable[Concatenate[T0, P1], T1]) -> None:
self.obj = obj
self.method = method

P2 = ParamSpec("P2")
T2 = TypeVar("T2")

def test_function(func: Callable[P2, T2], *args: P2.args, **kwargs: P2.kwargs) -> T2:
return func(*args, **kwargs)

t = TestClass(1, lambda i: i)
print(test_function(t.method, t.obj))

还有mypy错误:

file.py:26: error: Argument 1 to "test_function" has incompatible type "Callable[[int, **P1], T1]"; expected "Callable[[int, **P1], T1]"
file.py:26: error: Argument 2 to "test_function" has incompatible type "int"; expected "[int, **P1.args]"

我要做的是存储一个必须接受T0作为第一个arg的函数,并将其传递给一个接受任何的函数

问题是在__init__之后您丢失了P1T1信息,它没有附加到您的类中。在Generic中使用它们解决了问题:

from collections.abc import Callable
from typing import Concatenate, Generic, ParamSpec, TypeVar
T0 = TypeVar("T0")
P1 = ParamSpec("P1")
T1 = TypeVar("T1")

class TestClass(Generic[T0, P1, T1]):
def __init__(self, obj: T0, method: Callable[Concatenate[T0, P1], T1]) -> None:
self.obj = obj
self.method = method

P2 = ParamSpec("P2")
T2 = TypeVar("T2")

def test_function(func: Callable[P2, T2], *args: P2.args, **kwargs: P2.kwargs) -> T2:
return func(*args, **kwargs)
def mth(i: int) -> int:  # Instead of lambda, to avoid unexpected Any
return i


t = TestClass(1, mth)
print(test_function(t.method, t.obj))

(操场(。

严格地说,您可以期望mypy在解析类型vars后键入method,但这永远不会发生(在任何上下文中(。这将导致不明确的解决方案:它应该是Callable[[int], int]吗?Callable[[T0], int]Callable[[T0], T0]?还有别的吗?(我甚至不能说我个人更喜欢其中的哪一个,很难定义非模糊的,你必须记住泛型/协议,Callable本身和外部方法中的绑定类型变量,等等。(

相关内容

最新更新