下面的代码首先定义了Proto
协议,然后定义了一个函数,该函数接受一个遵循该协议的变量,然后定义了A
和B
类,我认为它们都遵循该协议,尽管只有B.__call__
的参数名与协议不同(在Proto
中是x
,在B
中是y
)。
mypy检查以下代码后,出现以下错误
main.py:20: error: Argument 1 to "func" has incompatible type "B"; expected "Proto"
看起来,协议不仅强制类型,还强制参数名称。这是预期的行为吗?还是mypy有什么问题?
from typing import Protocol
class Proto(Protocol):
def __call__(self, x: int) -> int:
...
def func(f: Proto):
pass
class A:
def __call__(self, x: int) -> int:
return x
class B:
def __call__(self, y: int) -> int:
return y
func(A())
func(B())
2条答案
按热度按时间pod7payv1#
可以将
Proto
p
调用为p(0)
或p(x=0)
。B
不满足第二个条件。如果希望B
有效,可以强制使用位置参数zi8p0yeb2#
或者,您可以使用
__dunder_beginning
名称来表示“我不关心该名称-允许任何名称”。mypy
支持此功能(文档在这里),它由PEP 484支持。Typeshed使用此语法,因此所有类型检查器都应该支持它。这是向后兼容的(posonly参数是在Python 3.8中引入的,而Python 3.7仍然有效)声明协议的方式不考虑参数名称。第一个
还有这个
这不适用于
*args
和**kwargs
,因为无论如何都不会考虑它们的名称。