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

Python中@overload用Union类型导致签名重叠错误,如何正确定义类型?

解决parse_as重载函数的mypy类型错误

我尝试编写一个名为parse_as的Python函数,用于将输入字节解析为指定类型,代码如下:

from typing import Any, TypeVar, overload

_T1 = TypeVar('_T1')
_T2 = TypeVar('_T2')
_T3 = TypeVar('_T3')


@overload
def parse_as(ty: type[_T1] | type[_T2], s: bytes) -> _T1 | _T2:
    ...


@overload
def parse_as(ty: type[_T1] | type[_T2] | type[_T3], s: bytes) -> _T1 | _T2 | _T3:
    ...


def parse_as(ty: Any, s: bytes) -> Any:
    raise NotImplementedError()

运行mypy时出现错误:

error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader

请问该如何正确表达这个函数的类型?另外,所有TypeVar均绑定同一类,这会有影响吗?


错误原因

mypy报错是因为联合类型的匹配逻辑:type[_T1] | type[_T2]这个类型实际上比type[_T1] | type[_T2] | type[_T3]更宽泛——Python的联合类型是无序且可扩展的,任何能匹配第二个重载参数的输入,都能被第一个重载的参数类型接受,因此第二个重载永远不会被触发。

正确的类型写法

不需要为不同数量的类型选项编写多个重载,而是使用可变长度类型变量元组(TypeVarTuple + Unpack)来支持任意数量的目标类型,这样既简洁又能覆盖所有情况:

from typing import Any, TypeVarTuple, Unpack, overload

# 定义可变长度的类型变量元组
_Ts = TypeVarTuple('_Ts')


@overload
def parse_as(ty: type[Unpack[_Ts]], s: bytes) -> Unpack[_Ts]:
    ...


def parse_as(ty: Any, s: bytes) -> Any:
    raise NotImplementedError()

如果你的需求是允许传入单个类型或多个类型的元组(比如parse_as((int, str), b'123')),可以调整重载为:

from typing import Any, TypeVar, TypeVarTuple, Unpack, overload

_T = TypeVar('_T')
_Ts = TypeVarTuple('_Ts')


@overload
def parse_as(ty: type[_T], s: bytes) -> _T:
    ...


@overload
def parse_as(ty: tuple[type[Unpack[_Ts]]], s: bytes) -> Unpack[_Ts]:
    ...


def parse_as(ty: Any, s: bytes) -> Any:
    raise NotImplementedError()

关于TypeVar绑定同一类的影响

如果所有TypeVar都绑定了同一个类(比如_T1 = TypeVar('_T1', bound=MyClass)),只会限制可解析的类型必须是该类的子类,不会影响重载的正确性。只要按照上述方式调整类型定义,mypy就能正确识别类型约束。

内容的提问来源于stack exchange,提问作者tibbe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 21:50:09