You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:22:22