如何让 Mypy 在 Callable 中识别 class 的协议成员资格?
How to get Mypy to recognize a class's protocol membership within a Callable?
当协议用作类型注释函数的简单参数时,Mypy 正确识别 class 对协议的遵守。但是,当我有一个函数需要使用该协议的可调用参数时,Mypy 会错过用户 class 的协议成员资格。
我是在滥用 Mypy 的协议模式,还是 Mypy 目前根本不支持这种模式?
(我已经看到关于 Mypy 在 Callables 上遇到问题的帖子 that get assigned to a class.. 所以这可能是一个已知行为)
from typing_extensions import Protocol
from typing import Callable
class P(Protocol) :
def foo(self) -> None : ...
def requires_P(protocol_member : P) -> None :
protocol_member.foo()
def requires_P_callable(protocol_member : P, function: Callable[[P],None]) -> None :
function(protocol_member)
class C :
def foo(self) :
print("bar")
if __name__ == '__main__' :
c = C()
def call_foo(c: C) -> None:
c.foo()
requires_P(c)
# mypy is fine with this
requires_P_callable(c, call_foo)
# mypy complains :
# Argument 2 to "requires_P_callable" has incompatible type "Callable[[C], None]"; expected "Callable[[P], None]"
如果将 call_foo 的定义替换为:
def call_foo(c: P) -> None:
c.foo()
错误消失,程序继续工作...如果停止使用协议并使 C 成为 P 的子节点,情况是一样的。
第二种解决方法是:
from typing import Callable, Protocol, TypeVar
_TP = TypeVar('_TP', bound='P')
class P(Protocol):
def foo(self) -> None:
...
class C:
def foo(self) -> None:
print("foo")
def requires_P_callable(prot: _TP, func: Callable[[_TP], None]) -> None:
func(prot)
def call_foo(c: C) -> None:
c.foo()
if __name__ == '__main__':
c = C()
requires_P_callable(c, call_foo)
当协议用作类型注释函数的简单参数时,Mypy 正确识别 class 对协议的遵守。但是,当我有一个函数需要使用该协议的可调用参数时,Mypy 会错过用户 class 的协议成员资格。
我是在滥用 Mypy 的协议模式,还是 Mypy 目前根本不支持这种模式?
(我已经看到关于 Mypy 在 Callables 上遇到问题的帖子 that get assigned to a class.. 所以这可能是一个已知行为)
from typing_extensions import Protocol
from typing import Callable
class P(Protocol) :
def foo(self) -> None : ...
def requires_P(protocol_member : P) -> None :
protocol_member.foo()
def requires_P_callable(protocol_member : P, function: Callable[[P],None]) -> None :
function(protocol_member)
class C :
def foo(self) :
print("bar")
if __name__ == '__main__' :
c = C()
def call_foo(c: C) -> None:
c.foo()
requires_P(c)
# mypy is fine with this
requires_P_callable(c, call_foo)
# mypy complains :
# Argument 2 to "requires_P_callable" has incompatible type "Callable[[C], None]"; expected "Callable[[P], None]"
如果将 call_foo 的定义替换为:
def call_foo(c: P) -> None:
c.foo()
错误消失,程序继续工作...如果停止使用协议并使 C 成为 P 的子节点,情况是一样的。
第二种解决方法是:
from typing import Callable, Protocol, TypeVar
_TP = TypeVar('_TP', bound='P')
class P(Protocol):
def foo(self) -> None:
...
class C:
def foo(self) -> None:
print("foo")
def requires_P_callable(prot: _TP, func: Callable[[_TP], None]) -> None:
func(prot)
def call_foo(c: C) -> None:
c.foo()
if __name__ == '__main__':
c = C()
requires_P_callable(c, call_foo)