Python 3.10:如何为继承Generic[TypeVar]的数据类正确类型提示__add__?
如何为温度单位类的魔法方法添加正确的类型提示
我开发了一个名为totemp的温度单位转换工具包(开发阶段),包含Celsius、Fahrenheit、Delisle、Kelvin、Newton、Rankine、Réaumur和Romer共8个数据类。当前Celsius类的__add__方法用@no_type_check绕过了mypy检查,尝试过抽象类、NewType都没解决类型提示问题,想知道怎么给__add__、__gt__/__lt__这类魔法方法正确添加类型提示。
当前Celsius类核心实现:
from dataclasses import dataclass, field from typing import Generic, TypeVar, no_type_check TEMP = TypeVar('TEMP', int, float) # TEMP must be int or float @dataclass class Celsius(Generic[TEMP]): """...""" __value: TEMP __symbol: str = field(compare=False, repr=False, default='ºC') def __str__(self) -> str: return f'{self.__value}{self.__symbol}' def __repr__(self) -> str: return f'Celsius({self.__value})' @no_type_check def __add__(self, other): match str(type(other)): case "<class 'totemp.temperature_types.Celsius'>": return Celsius(self.__value + other.value) case _: try: other = other.to_celsius() return Celsius(self.__value + other.value) except AttributeError as error: print( f'\033[31;1mAttributeError: {error}.\n ' + f"Cause: '{other}' is not a temperature scale.\033[m" ) def to_fahrenheit(self) -> 'Fahrenheit[TEMP]': fahrenheit = type(self.__value)(self.__value * 9 / 5 + 32) return Fahrenheit(fahrenheit)
解决方案:基于抽象基类统一类型约束
步骤1:定义抽象基类统一接口
先创建一个抽象基类,让所有温度类继承,定义通用的转换方法和公共属性访问器,给类型检查器提供明确的类型边界。
from abc import ABC, abstractmethod from dataclasses import dataclass, field from typing import Generic, TypeVar # 约束数值类型为int/float TEMP = TypeVar('TEMP', int, float) # 约束所有温度类的类型变量,绑定到抽象基类 TempType = TypeVar('TempType', bound='Temperature') @dataclass class Temperature(ABC, Generic[TEMP]): _value: TEMP _symbol: str = field(compare=False, repr=False) @property def value(self) -> TEMP: return self._value @abstractmethod def to_celsius(self) -> 'Celsius[TEMP]': """转换为摄氏度的抽象方法""" ... @abstractmethod def __add__(self, other: TempType) -> 'Celsius[TEMP]': ... @abstractmethod def __gt__(self, other: TempType) -> bool: ... @abstractmethod def __lt__(self, other: TempType) -> bool: ...
步骤2:修改Celsius类继承抽象基类
移除@no_type_check,基于抽象基类的接口实现魔法方法并添加类型提示:
@dataclass class Celsius(Temperature[TEMP]): _symbol: str = field(compare=False, repr=False, default='ºC') def __str__(self) -> str: return f'{self.value}{self._symbol}' def __repr__(self) -> str: return f'Celsius({self.value})' def __add__(self, other: TempType) -> 'Celsius[TEMP]': # 统一转换为摄氏度后计算 other_celsius = other.to_celsius() return Celsius(self.value + other_celsius.value) def __gt__(self, other: TempType) -> bool: other_celsius = other.to_celsius() return self.value > other_celsius.value def __lt__(self, other: TempType) -> bool: other_celsius = other.to_celsius() return self.value < other_celsius.value def to_celsius(self) -> 'Celsius[TEMP]': return self def to_fahrenheit(self) -> 'Fahrenheit[TEMP]': fahrenheit_val = type(self.value)(self.value * 9 / 5 + 32) return Fahrenheit(fahrenheit_val)
步骤3:其他温度类的统一实现
以Fahrenheit为例,只需继承抽象基类并实现抽象方法即可,类型提示会自动适配:
@dataclass class Fahrenheit(Temperature[TEMP]): _symbol: str = field(compare=False, repr=False, default='ºF') def __str__(self) -> str: return f'{self.value}{self._symbol}' def __repr__(self) -> str: return f'Fahrenheit({self.value})' def __add__(self, other: TempType) -> 'Celsius[TEMP]': other_celsius = other.to_celsius() self_celsius = self.to_celsius() return Celsius(self_celsius.value + other_celsius.value) def __gt__(self, other: TempType) -> bool: other_celsius = other.to_celsius() self_celsius = self.to_celsius() return self_celsius.value > other_celsius.value def __lt__(self, other: TempType) -> bool: other_celsius = other.to_celsius() self_celsius = self.to_celsius() return self_celsius.value < other_celsius.value def to_celsius(self) -> 'Celsius[TEMP]': celsius_val = type(self.value)((self.value - 32) * 5 / 9) return Celsius(celsius_val)
关键说明
- 类型变量绑定:通过
TempType = TypeVar('TempType', bound='Temperature'),让mypy明确识别other是任意温度类实例,且拥有to_celsius等统一方法。 - 属性访问优化:将私有
__value改为受保护的_value,并通过@property暴露value,避免类型检查器无法识别私有属性的问题。 - 统一逻辑:所有魔法方法基于
to_celsius转换实现,既保证功能一致性,也让类型提示准确无误,无需再用@no_type_check绕过检查。
内容的提问来源于stack exchange,提问作者eddyxide
相关产品推荐
相关产品推荐

