如何测试两个Protocol是否互为结构子类型?
你定义了两个Protocol:
class TooComplexProtocolInNeedOfRefactoring(Protocol): @property def useful(self) -> int: ... @property def irrelevant1(self) -> int: ... @property def irrelevant2(self) -> int: ... @property def irrelevant3(self) -> int: ...
class SpecificSubProtocol(Protocol): @property def useful(self) -> int: ...
需要验证所有实现TooComplexProtocolInNeedOfRefactoring的类都能兼容SpecificSubProtocol(即前者是后者的结构子类型),之前直接赋值Type[SpecificSubProtocol]的方式会报错,因为Type[X]要求的是具体类,而Protocol本身是抽象类型。
以下是两种可行的验证方式:
方式一:利用函数参数的静态类型检查
通过定义一个接受SpecificSubProtocol类型参数的函数,再传入一个标注为TooComplexProtocolInNeedOfRefactoring的变量,让静态类型检查器(如mypy、pyright)自动验证兼容性:
from typing import Protocol, TypeVar # 定义绑定到复杂Protocol的TypeVar T = TypeVar("T", bound=TooComplexProtocolInNeedOfRefactoring) class TooComplexProtocolInNeedOfRefactoring(Protocol): @property def useful(self) -> int: ... @property def irrelevant1(self) -> int: ... @property def irrelevant2(self) -> int: ... @property def irrelevant3(self) -> int: ... class SpecificSubProtocol(Protocol): @property def useful(self) -> int: ... # 定义接受SpecificSubProtocol的函数 def process_specific(sub: SpecificSubProtocol) -> None: pass # 模拟返回符合复杂Protocol的实例的函数 def get_complex_instance() -> T: ... # 传递实例给process_specific,类型检查器会验证兼容性 process_specific(get_complex_instance())
如果TooComplexProtocolInNeedOfRefactoring不是SpecificSubProtocol的结构子类型,类型检查器会抛出类似Argument 1 has incompatible type "TooComplexProtocolInNeedOfRefactoring"; expected "SpecificSubProtocol"的错误。反之则无报错,说明结构子类型关系成立。
方式二:直接使用类型断言验证
可以通过类型断言的方式让类型检查器验证两个Protocol的兼容性:
# 定义一个符合复杂Protocol的变量 complex_proto: TooComplexProtocolInNeedOfRefactoring = ... # 断言它属于SpecificSubProtocol类型,类型检查器会验证是否兼容 specific_proto: SpecificSubProtocol = complex_proto
同样,如果兼容性不成立,类型检查器会直接报错。
关键说明
结构子类型是静态类型系统的概念,验证依赖于mypy、pyright这类静态类型检查工具,而非运行时检查。Protocol本身在运行时只是普通类,无法通过运行时代码直接验证结构子类型关系。
内容的提问来源于stack exchange,提问作者Anaphory

