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

如何让typing/mypy识别通过__extends__定义的动态超类继承关系

解决方案

共有4种可落地的方案,均不会破坏现有运行时的类合并逻辑:

方案1:类内self类型绑定

如果仅需要在B类的内部代码中正常访问A的属性,不需要全局识别子类型关系,可直接给B的self加类型绑定:

from typing import TypeVar

# 绑定到A类型
AT = TypeVar('AT', bound='A')

class B(Pluggable):
    __extends__ = A
    # 仅类型检查阶段生效,告知mypy self同时属于A类型
    self: AT
    
    def demo_method(self):
        # 这里访问A的属性不会报错
        print(self.a_attr)

方案2:TYPE_CHECKING 条件继承

改造成本最低的全局兼容方案,仅在类型检查阶段声明继承关系,运行时完全无感知:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    # 类型检查阶段显式继承A
    _Parent = A
else:
    # 运行时保持原继承逻辑,不影响类合并、MRO生成
    _Parent = Pluggable

class B(_Parent):
    __extends__ = A

方案3:ABC虚拟子类注册

如果需要全局声明子类型关系,可通过ABC的注册机制实现,运行时不会改变真实继承链:

from abc import ABC

# 仅需要让A继承ABC即可,无需修改其他逻辑
class A(Pluggable, ABC):
    ...

class B(Pluggable):
    __extends__ = A

# 注册虚拟继承,mypy会识别该关系,运行时无实际继承行为
A.register(B)

方案4:自定义mypy插件自动识别

如果项目中这类__extends__声明的类很多,可写一个极简mypy插件自动批量处理:

  1. 编写插件代码:
from mypy.nodes import TypeInfo
from mypy.plugin import Plugin, ClassDefContext

class ExtendsAttrPlugin(Plugin):
    def analyze_class(self, ctx: ClassDefContext) -> None:
        cls_info: TypeInfo = ctx.cls.info
        extends_entry = cls_info.names.get('__extends__')
        if not extends_entry or not extends_entry.type:
            return
        parent_type_info = extends_entry.type.type
        # 自动给当前类添加父类型关系
        cls_info.mro.insert(1, parent_type_info)
        cls_info.bases.append(extends_entry.type)

def plugin(version: str):
    return ExtendsAttrPlugin
  1. 在mypy配置文件(mypy.ini/pyproject.toml)中添加插件加载配置:
[mypy]
plugins = path/to/your/extends_attr_plugin.py

该方案无需修改任何业务代码,即可让mypy自动识别所有__extends__声明的继承关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 21:09:00