使用 mypy 检查协议子类的 python 函数签名的类型

问题描述 投票:0回答:1

有没有一种方法可以安全地对子类协议的Python类进行类型检查?

如果我定义具有特定方法函数签名的协议,则隐式子类必须定义具有兼容签名的方法:

# protocols.py

from abc import abstractmethod
from dataclasses import dataclass
from typing import Protocol

class SupportsPublish(Protocol):
    @abstractmethod
    def publish(self, topic: str):
        ...

def publish(m: SupportsPublish):
    m.publish("topic")

@dataclass
class Publishable:
    foo: str = "bar"

    def publish(self):
        print(self)

publish(Publishable())

# ✗ mypy protocols.py       
# protocols.py:24: error: Argument 1 to "publish" has incompatible type "Publishable"; expected "SupportsPublish"  [arg-type]
# protocols.py:24: note: Following member(s) of "Publishable" have conflicts:
# protocols.py:24: note:     Expected:
# protocols.py:24: note:         def publish(self, topic: str) -> Any
# protocols.py:24: note:     Got:
# protocols.py:24: note:         def publish(self) -> Any
# Found 1 error in 1 file (checked 1 source file)

但是,如果我显式子类型

SupportsPublish
,mypy 不会报告类型错误:

...
@dataclass
class Publishable(SupportsPublish):
...

# ✗ mypy protocols.py
# Success: no issues found in 1 source file

基于 PEP 中的这个简介,我希望类型检查器能够找到函数签名不匹配的地方:

请注意,显式子类和隐式子类之间没有什么区别,显式子类化的主要好处是“免费”获得一些协议方法。此外,类型检查器可以静态验证该类是否确实正确实现了协议:

这是我的环境:


> mypy --version
mypy 1.3.0 (compiled: yes)
> python --version
Python 3.9.17

我希望 mypy 指出函数签名不匹配。

python types mypy
1个回答
0
投票

publish
方法在类中必须具有与协议中相同的签名以符合协议。 这是支持
mypy --strict
的版本:

from abc import abstractmethod
from dataclasses import dataclass
from typing import Protocol

class SupportsPublish(Protocol):
    @abstractmethod
    def publish(self, topic: str) -> None:
        ...

def publish(m: SupportsPublish) -> None:
    m.publish("topic")

@dataclass
class Publishable:
    foo: str = "bar"

    def publish(self, topic: str) -> None:
        print(topic)

publish(Publishable())
© www.soinside.com 2019 - 2024. All rights reserved.