如何让函数返回与基类重写方法对应的实例类型?
解决方案
要实现让fn的返回值类型自动对应参数子类中get_type返回的类的实例,需要通过泛型抽象类和绑定的类型变量来实现,具体步骤如下:
1. 调整类型变量与抽象基类定义
首先定义一个绑定到任意类型的TypeVar,并让MyClass成为泛型抽象类,将类型变量关联到get_type的返回类型:
from abc import ABC, abstractmethod from decimal import Decimal from fractions import Fraction from typing import Type, TypeVar, Generic # 定义类型变量,代表get_type返回类的实例类型 InstanceT = TypeVar('InstanceT') class MyClass(ABC, Generic[InstanceT]): @classmethod @abstractmethod def get_type(cls) -> Type[InstanceT]: ...
2. 子类继承时指定具体类型
每个子类继承MyClass时,明确指定对应的实例类型(即get_type要返回的类):
class MyDecimalSubclass(MyClass[Decimal]): @classmethod def get_type(cls) -> Type[Decimal]: return Decimal class MyFractionSubclass(MyClass[Fraction]): @classmethod def get_type(cls) -> Type[Fraction]: return Fraction
3. 为函数fn添加泛型类型注解
让fn接收泛型参数InstanceT,并将参数类型指定为MyClass[InstanceT],返回值类型直接设为InstanceT:
def fn(arg: MyClass[InstanceT]) -> InstanceT: value = arg.get_type()("100") return value
最终完整代码
from abc import ABC, abstractmethod from decimal import Decimal from fractions import Fraction from typing import Type, TypeVar, Generic InstanceT = TypeVar('InstanceT') class MyClass(ABC, Generic[InstanceT]): @classmethod @abstractmethod def get_type(cls) -> Type[InstanceT]: ... class MyDecimalSubclass(MyClass[Decimal]): @classmethod def get_type(cls) -> Type[Decimal]: return Decimal class MyFractionSubclass(MyClass[Fraction]): @classmethod def get_type(cls) -> Type[Fraction]: return Fraction def fn(arg: MyClass[InstanceT]) -> InstanceT: value = arg.get_type()("100") return value my_fraction = fn(MyFractionSubclass()) # 类型推断为Fraction my_decimal = fn(MyDecimalSubclass()) # 类型推断为Decimal print(my_fraction, my_decimal)
为什么原方案不生效?
- 原代码中的
TypeVar没有与MyClass绑定,类型检查器无法将子类的get_type返回类型与函数返回值关联起来。 "arg.get_type()()"这种写法不属于Python类型注解的合法语法,类型检查器无法解析这种动态表达式。
后续新增MyClass子类时,只需要在继承时指定对应的实例类型即可,类型检查器会自动推断fn的返回值类型。
内容的提问来源于stack exchange,提问作者Michael Pacheco
相关产品推荐
相关产品推荐

