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

List类型标注用Union遇兼容问题,求多类型列表正确类型提示

问题与解决方案

问题重现

以下代码运行mypy时会触发两个类型错误:

from typing import Union, List


def homogenize(l: List[Union[str, int]]) -> List[str]:
    return [str(i) for i in l]


x = [0, 5]
homogenize(x) # <-- 错误:`List[int]` 与 `List[Union[str, int]]` 不兼容

y = [0, 'cat']
homogenize(y) # <-- 错误:`List[object]` 与 `List[Union[str, int]]` 不兼容

报错细节:

  • 变量x类型为List[int],无法匹配参数标注的List[Union[str, int]]
  • 变量y被自动推断为List[object],同样不符合参数类型要求

核心疑问:函数本应接收包含int或str的列表,为何纯int列表不被允许?如何正确标注这类列表的类型?

原因分析

Python的List类型是**不变(invariant)**的,即只有当两个列表的元素类型完全一致时,它们的类型才兼容。哪怕int是Union[str, int]的子集,List[int]也不能被视为List[Union[str, int]]的子类——这是为了类型安全:如果允许此类赋值,函数理论上可以往列表中添加str元素,而原List[int]根本无法存储str,会引发类型混乱。

另外,y = [0, 'cat']被推断为List[object],是因为Python默认会将包含多种不同类型元素的列表,推断为所有元素的最宽泛公共父类型(此处为object),而非期望的Union[str, int]。

解决方案

1. 用协变迭代类型替代List

由于函数仅需遍历读取元素、无需修改列表,可使用Iterable[Union[str, int]]或Sequence[Union[str, int]]作为参数类型。这两种类型是协变的,允许传入元素类型为Union[str, int]子集的容器:

from typing import Union, Iterable


def homogenize(l: Iterable[Union[str, int]]) -> List[str]:
    return [str(i) for i in l]


x = [0, 5]
homogenize(x) # 类型检查通过

y: List[Union[str, int]] = [0, 'cat']
homogenize(y) # 类型检查通过

2. 显式标注混合类型列表的类型

对于y这类混合元素列表,需显式标注其类型为List[Union[str, int]],避免Python自动推断为List[object]:

y: List[Union[str, int]] = [0, 'cat']

3. 使用泛型提升灵活性

如果希望函数能处理任意可转换为字符串的类型,可结合泛型实现更灵活的约束:

from typing import Iterable, TypeVar

StrCastable = TypeVar('StrCastable', str, int)

def homogenize(l: Iterable[StrCastable]) -> List[str]:
    return [str(i) for i in l]

该方案既保证类型安全,又允许函数接收List[int]、List[str]或List[Union[str, int]]类型的参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:07:11