结合classmethod、类对象与泛型使用时mypy报错问题排查
mypy报错"type[T]" has no attribute "model_validate"的原因与解决方法
问题场景
我用以下代码创建泛型类G的实例,并传入模型类型:
from typing import TypeVar, Type class A: @classmethod def model_validate(cls): print('Done') T = TypeVar('T', bound=A) class G[T]: def __init__(self, model: Type[T]): self.model = model def func(self) -> None: print(self.model.model_validate()) G[A](A).func()
代码运行正常,但mypy抛出错误:
error: "type[T]" has no attribute "model_validate" [attr-defined]
原因分析
mypy对泛型参数的类型推导逻辑比较严格:虽然T被绑定到A,但Type[T]表示的是T对应的类对象类型,mypy无法自动关联到A中定义的model_validate类方法——它只知道Type[T]是一个类类型,但不确定这个类有没有该方法。
解决办法
方法1:用协议约束Type[T]的结构
定义一个协议,明确要求类必须包含model_validate类方法,然后让Type[T]遵守这个协议:
from typing import TypeVar, Type, Protocol class A: @classmethod def model_validate(cls): print('Done') # 定义协议,规定必须有model_validate类方法 class ModelProtocol(Protocol): @classmethod def model_validate(cls) -> None: ... T = TypeVar('T', bound=A) class G[T]: # 同时约束Type[T]和协议 def __init__(self, model: Type[T] & ModelProtocol): self.model = model def func(self) -> None: print(self.model.model_validate()) G[A](A).func()
方法2:直接绑定到Type[A](简化场景)
如果你的G类只需要处理A及其子类,没必要用泛型的Type[T],直接用Type[A]做类型注解即可:
from typing import TypeVar, Type class A: @classmethod def model_validate(cls): print('Done') T = TypeVar('T', bound=A) class G[T]: def __init__(self, model: Type[A]): self.model = model def func(self) -> None: print(self.model.model_validate()) G[A](A).func()
方法3:类型断言(快速修复)
如果不想修改类型注解,可以在调用方法时用类型断言告诉mypy这个类对象确实有该方法:
def func(self) -> None: print((self.model).model_validate())
内容的提问来源于stack exchange,提问作者KOLYAN CAT4UP
相关产品推荐
相关产品推荐

