有没有一种方法可以安全地对子类协议的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 指出函数签名不匹配。
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())