0

当协议用作类型注释函数的简单参数时,Mypy 可以正确识别类对协议的遵守情况。但是,当我有一个需要使用该协议的可调用参数的函数时,Mypy 会错过用户类的协议成员资格。

我是在滥用 Mypy 的协议模式,还是 Mypy 目前根本不支持这种模式?

(我已经看到有关 Mypy 在分配给一个类的 Callables 方面遇到问题的线程......所以这可能是一个已知的行为)

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]"



4

1 回答 1

0

如果将 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)
于 2020-04-24T20:44:59.253 回答