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

如何测试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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:01:09