如何测试Python类未直接继承typing.Protocol实例
问题:禁止直接继承typing.Protocol实例
我需要确保团队开发者不会直接继承typing.Protocol实例。也就是说,类可以实现Protocol定义的接口,但绝对不能用class MyClass(MyProtocol):这种写法——这种写法会强制类成为Protocol的子类,哪怕类根本没实现任何属性和方法逻辑,也能通过isinstance(MyClass(), MyProtocol)检查。
问题示例
from typing import Protocol class MyProtocol(Protocol): def foo(self): raise NotImplementedError("Don't subclass MyProtocol!") class MyClass(MyProtocol): pass # MyClass因继承Protocol而拥有foo方法... assert hasattr(MyClass(), 'foo')
需求实现
需要编写一个测试函数,仅当目标对象(或类)未采用显式继承Protocol的语法定义时返回True:
def does_not_subclass_protocol(obj, protocol): # 仅当obj未采用MyClass(MyProtocol)这类定义语法时返回True
解决方案
通过检查类的方法解析顺序(MRO)来判断是否存在显式继承关系:
def does_not_subclass_protocol(obj, protocol): # 区分传入的是实例还是类本身 target_cls = obj if isinstance(obj, type) else obj.__class__ # 检查Protocol是否在类的继承链中 return protocol not in target_cls.__mro__
测试验证
1. 显式继承的情况(不符合要求)
class MyProtocol(Protocol): def foo(self): ... class BadClass(MyProtocol): pass # 实例检查返回False assert does_not_subclass_protocol(BadClass(), MyProtocol) is False # 类本身检查返回False assert does_not_subclass_protocol(BadClass, MyProtocol) is False
2. 结构子类型实现(符合要求)
class GoodClass: def foo(self): return "hello" # 实例检查返回True assert does_not_subclass_protocol(GoodClass(), MyProtocol) is True # 类本身检查返回True assert does_not_subclass_protocol(GoodClass, MyProtocol) is True # 结构子类型依然能正常通过Protocol的类型检查 assert isinstance(GoodClass(), MyProtocol) is True
说明
这个函数的核心逻辑是:如果目标类的MRO中包含指定的Protocol,说明代码中使用了显式继承语法;反之则是通过结构子类型实现的接口,符合要求。同时该方法也能检测间接继承的情况(比如继承了一个已经继承Protocol的类)。
内容的提问来源于stack exchange,提问作者philosofool
相关产品推荐
相关产品推荐

