python-3.x 当参数名与键入时定义的不同时发生mypy错误,协议

yfwxisqw  于 2022-11-19  发布在  Python
关注(0)|答案(2)|浏览(118)

下面的代码首先定义了Proto协议,然后定义了一个函数,该函数接受一个遵循该协议的变量,然后定义了AB类,我认为它们都遵循该协议,尽管只有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())
pod7payv

pod7payv1#

可以将Protop调用为p(0)p(x=0)B不满足第二个条件。如果希望B有效,可以强制使用位置参数

class Proto(Protocol):
    def __call__(self, x: int, /) -> int:
        ...
zi8p0yeb

zi8p0yeb2#

  • 注意:此答案是为需要向后兼容性的用户提供的:对于python 3.8及更高版本,请使用仅限位置参数声明。*

或者,您可以使用__dunder_beginning名称来表示“我不关心该名称-允许任何名称”。mypy支持此功能(文档在这里),它由PEP 484支持。Typeshed使用此语法,因此所有类型检查器都应该支持它。这是向后兼容的(posonly参数是在Python 3.8中引入的,而Python 3.7仍然有效)声明协议的方式不考虑参数名称。
第一个
还有这个
这不适用于*args**kwargs,因为无论如何都不会考虑它们的名称。

相关问题