如何在Python中为泛型函数实现基于类属性的条件类型注解?
实现类型注解的解决方案
推荐方案:将基类改为泛型类(类型检查最准确)
通过把基类A定义为泛型类,可以让类型检查器准确推断some_field的类型,完全匹配type_field对应的实例类型:
from typing import Type, TypeVar, Generic # 定义用于表示字段实例类型的泛型变量 InstanceType = TypeVar('InstanceType') class A(Generic[InstanceType]): type_field: Type[InstanceType] = int class B(A[str]): type_field: Type[str] = str # 绑定到A泛型实例的TypeVar T = TypeVar('T', bound=A[InstanceType]) def func(obj: T, some_field: InstanceType): # 函数逻辑实现 pass # 合法调用示例 func(A(), 123) # 类型检查器会提示传入int,符合要求 func(B(), "hello") # 类型检查器会提示传入str,符合要求 # 非法调用会被类型检查器拦截 # func(A(), "hello") # 错误:期望int类型参数 # func(B(), 123) # 错误:期望str类型参数
这种方案通过泛型参数把type_field对应的实例类型抽象出来,派生类B继承时明确指定实例类型为str,函数func的some_field类型会自动与obj所属类的type_field实例类型保持一致,类型提示准确且代码结构清晰。
兼容方案:不修改原有基类(依赖类型检查器特性)
如果无法修改A和B的原有定义,可以利用类型检查器对类属性类型的解析能力,提取type_field中的实例类型:
from typing import Type, TypeVar class A: type_field: Type[int] = int class B(A): type_field: Type[str] = str # 绑定到A或其子类的TypeVar T = TypeVar('T', bound=A) def func(obj: T, some_field: T.type_field.__args__[0]): # 函数逻辑实现 pass # 合法调用示例 func(A(), 123) # 类型检查器识别为int类型参数 func(B(), "hello") # 类型检查器识别为str类型参数
这种写法通过T.type_field.__args__[0]提取Type[int]/Type[str]中的实例类型,依赖mypy、pyright等主流类型检查器的特性支持,属于相对hack的写法,推荐优先使用泛型类方案。
内容的提问来源于stack exchange,提问作者Aleksandr Lobanov
相关产品推荐
相关产品推荐

