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

如何让Mypy认可经类装饰器处理后的FormA、FormB继承自FormBase?

解决Mypy对类装饰器类型识别的问题

你的代码运行逻辑正常,但Mypy报错是因为它默认无法识别装饰器会替换原类的类型——原FormA/FormB本身确实没继承FormBase,但装饰器返回的新类是FormBase的子类,Mypy需要明确的类型注解来追踪这个转换。

修复方案:用TypeVar和Generic正确标注装饰器类型

通过泛型类型注解,让Mypy清楚装饰器接收任意类,并返回一个FormBase的子类类型。修改后的代码如下:

from abc import ABC, abstractmethod
from typing import Any, TypeVar, Generic

# 定义泛型变量,代表任意类类型
T = TypeVar('T')

class FormBase(ABC):
    @abstractmethod
    def fn(self) -> str:
        pass

# 用Generic[T]标注装饰器,明确输入和输出的类型关系
def form(cls: type[T]) -> type[FormBase]:
    class NewClass(FormBase):
        def fn(self) -> str:
            return cls.__name__
    return NewClass

@form
class FormA:
    pass

@form
class FormB:
    pass

# 现在Mypy会认可FormA/FormB是FormBase的子类类型
forms: list[type[FormBase]] = [FormA, FormB]

for f in forms:
    print(f().fn())

为什么这样能解决问题?

  • TypeVar('T')用来捕获被装饰类的原始类型,结合装饰器的返回类型type[FormBase],能让Mypy理解装饰器是一个类型转换函数。
  • 泛型标注补充了类型转换的上下文,Mypy会正确推断被装饰后的FormA/FormB属于type[FormBase]类型,不再抛出继承关系错误。

另一种简化方案:直接给被装饰类加类型标注

如果不想用泛型,也可以在定义FormA/FormB时显式指定类型,强制Mypy识别:

@form
class FormA:
    pass
FormA: type[FormBase]  # 显式指定类型

@form
class FormB:
    pass
FormB: type[FormBase]

这种方式更直接,但不如泛型方案优雅,适合简单场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:05:17