如何让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
相关产品推荐
相关产品推荐

