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

如何正确为foo(Bar | None)调用场景添加Python类型提示?

问题:为支持UnionType参数的函数正确添加类型提示

当调用foo(Bar | None)时,mypy提示No overload variant of "foo" matches argument type "UnionType",原代码如下:

from typing import TypeVar, Type, overload

T = TypeVar('T')


@overload
def foo(bar: Type[T]) -> T:
    ...

@overload
def foo(bar: Type[T] | None) -> T | None:
    ...


def foo(bar: Type[T] | None) -> T | None:
    # implementation goes here
    ...


class Bar:
    ...


bar = foo(Bar)
bar2 = foo(Bar | None)  # No overload variant of "foo" matches argument type "UnionType"

尝试过的方案及问题:

  • 使用Type[T | None]作为参数类型,mypy提示“Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader”;
  • 移除第二个重载,仅保留Type[T]的参数类型,mypy仍提示“No overload variant of "foo" matches argument type "UnionType"”。

正确的类型提示方案

核心问题是Bar | None属于UnionType,原签名中的Type[T]无法直接匹配联合类型。以下是两种可行的解决方式:

方式一:简化签名,让类型变量支持联合类型

不需要重载,直接调整主函数签名,让T可以接受联合类型作为实参:

from typing import TypeVar, Type

T = TypeVar('T')

def foo(bar: Type[T] | None) -> T | None:
    if bar is None:
        return None
    # 根据实际需求实现逻辑,示例返回类实例
    if hasattr(bar, '__union_params__'):
        # 处理联合类型,这里示例返回第一个类型的实例
        return bar.__union_params__[0]()
    return bar()


class Bar:
    ...


bar = foo(Bar)  # mypy推断类型为Bar
bar2 = foo(Bar | None)  # mypy推断类型为Bar | None

方式二:添加联合类型专属重载(可选)

如果需要更精细的类型区分,可以添加针对联合类型的重载签名:

from typing import TypeVar, Type, overload, Union

T = TypeVar('T')
U = TypeVar('U')


@overload
def foo(bar: Type[T]) -> T:
    ...

@overload
def foo(bar: None) -> None:
    ...

@overload
def foo(bar: Union[Type[T], Type[U]]) -> Union[T, U]:
    ...

@overload
def foo(bar: Union[Type[T], Type[U], None]) -> Union[T, U, None]:
    ...


def foo(bar: object) -> object:
    # 实际实现逻辑
    if bar is None:
        return None
    if isinstance(bar, type):
        return bar()
    if hasattr(bar, '__union_params__'):
        # 示例逻辑:返回第一个类型实例
        return bar.__union_params__[0]()
    raise ValueError("Invalid argument type")


class Bar:
    ...


bar = foo(Bar)  # Bar
bar2 = foo(Bar | None)  # Bar | None
bar3 = foo(int | str)  # int | str

关键说明

  • Bar | None本质是Union[Bar, None],类型变量T默认支持联合类型作为实参,无需额外约束;
  • 原重载冲突是因为Type[T | None]被Type[T]覆盖(T可以是任意类型,包括联合类型),因此不需要单独为Type[T | None]写重载;
  • 只要签名允许T为联合类型,mypy就能正确推断返回值的联合类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:42:25