You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用mypy安全检查Protocol子类的Python函数签名?

如何安全检查继承Protocol的Python类的类型?

当定义带有特定方法签名的Protocol时,隐式实现该协议的类会被mypy正确检测出签名不兼容问题,但显式继承该Protocol的类即使方法签名不匹配,mypy默认也不会报错,具体场景如下:

隐式实现的情况(mypy正确报错)

# 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)

显式继承的情况(mypy默认不报错)

将Publishable改为显式继承SupportsPublish:

@dataclass
class Publishable(SupportsPublish):
    foo: str = "bar"

    def publish(self):
        print(self)

运行mypy protocols.py会提示Success: no issues found in 1 source file,但这不符合PEP 0544中类型检查器应验证显式实现正确性的要求。


解决方案

1. 启用mypy的协议成员检查选项

mypy默认关闭了对显式继承Protocol的类的成员签名检查,只需启用--protocol-member-checking选项(或包含该选项的--strict模式)即可触发检查:

mypy --protocol-member-checking protocols.py

此时mypy会正确检测出签名不匹配的错误,输出与隐式实现时一致的报错信息。

2. 结合运行时检查(可选)

若需要运行时也能验证类是否符合Protocol,可以给SupportsPublish添加@runtime_checkable装饰器:

from typing import Protocol, runtime_checkable

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

之后可以用isinstance(Publishable(), SupportsPublish)在运行时检查,但注意运行时检查仅验证方法是否存在,无法检测签名兼容性,仍需配合静态类型检查确保签名正确。


内容的提问来源于stack exchange,提问作者Andrew Stewart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 03:59:56