如何使用Generic或Union为__new__方法实现添加类型提示?
解决StrOrDecimal类__new__方法的类型兼容问题
问题描述
我实现了一个StrOrDecimal类,它可以存储str或decimal.Decimal实例,且继承自传入的str或decimal.Decimal类。目前通过@typing.overload实现的__new__方法可以正常通过mypy检查并运行,但当使用typing.Union[str, decimal.Decimal]或类型变量T作为参数类型注解时,会触发如下类型不兼容错误:
'generic.py:19: error: Argument 1 to "new" of "StrOrDecimal" has incompatible type "Type[generic.StrOrDecimalTyped.Decimal.StrOrDecimal[Any]]"; expected "Type[generic.StrOrDecimal[T]]"'
核心原因
错误源于类型变量T的绑定逻辑与__new__方法的参数类型不匹配,mypy无法正确推断传入的基类与返回实例之间的类型关联。
修复步骤
1. 定义受限类型变量
先声明一个仅允许str或decimal.Decimal类对象的类型变量,缩小类型范围:
from typing import TypeVar, overload, Type, Union import decimal T = TypeVar("T", bound=Union[type[str], type[decimal.Decimal]])
2. 明确重载签名与类型注解
针对两种基类分别编写__new__的重载签名,并在通用实现中使用正确的类型注解,让mypy能清晰识别输入输出的类型关系:
class StrOrDecimal: @overload def __new__(cls: Type["StrOrDecimal"], base: Type[str], value: str) -> str: ... @overload def __new__(cls: Type["StrOrDecimal"], base: Type[decimal.Decimal], value: str) -> decimal.Decimal: ... def __new__(cls: Type["StrOrDecimal"], base: T, value: str) -> T: instance = base(value) # 添加自定义存储逻辑 return instance
3. 泛型类场景的优化(可选)
如果需要将StrOrDecimal定义为泛型类,需明确泛型参数的绑定关系,避免类型模糊:
from typing import Generic class StrOrDecimal(Generic[T]): @overload def __new__(cls: Type["StrOrDecimal[str]"], base: Type[str], value: str) -> str: ... @overload def __new__(cls: Type["StrOrDecimal[decimal.Decimal]"], base: Type[decimal.Decimal], value: str) -> decimal.Decimal: ... def __new__(cls, base: T, value: str) -> T: instance = base(value) # 自定义逻辑 return instance
验证
调整后,mypy可以正确推断传入str或decimal.Decimal类时返回的实例类型,类型不兼容错误会消失,代码也能正常运行。
内容的提问来源于stack exchange,提问作者spacether
相关产品推荐
相关产品推荐

