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

Python类型注解:如何指定变量同时具备多种类型?

解决Python类型注解中“同时具备多种类型”的标注问题

核心结论

要表示变量同时具备多种类型(而非二选一),Python类型系统支持交集类型(使用&符号),这正是你要找的类似Union但表示“且”的标注方式。此外,也可以通过自定义Protocol来定义复合类型。

针对你的场景的解决方案

你遇到的mypy报错,本质是Iterable本身不包含__len__方法(不属于Sized类型),因此直接对Iterable调用len()会触发类型检查错误。下面提供两种可行方案:

方案1:直接使用交集类型标注

Python 3.10+和mypy都支持用&表示交集类型,直接标注参数同时是Iterable和Sized:

from typing import Iterable, Sized, TypeVar

D1 = TypeVar('D1')
D2 = TypeVar('D2')

def your_function(a: Iterable[D1] & Sized, b: Iterable[D2] & Sized) -> int:
    return len(a) + len(b)

这样mypy会识别到a和b同时具备Iterable的迭代能力和Sized的len()方法,不会再报错。

方案2:自定义复合类型Protocol

如果需要多次复用这个复合类型,可以用Protocol定义一个同时继承Iterable和Sized的协议(无需实现任何方法,只需定义结构):

from typing import Iterable, Sized, Protocol, TypeVar

T = TypeVar('T')

class SizedIterable(Iterable[T], Sized, Protocol):
    """同时具备Iterable和Sized特性的类型"""
    pass

# 之后就可以直接用这个自定义类型标注
def your_function(a: SizedIterable[D1], b: SizedIterable[D2]) -> int:
    return len(a) + len(b)

像list、tuple、set这类内置类型,天然符合SizedIterable的结构,传入它们不会触发类型错误。

为什么你之前的泛型类方案失效?

如果之前直接定义普通泛型类(而非Protocol):

# 错误示例:普通类需要实现抽象方法,无法直接用于类型标注
from typing import Iterable, Sized, Generic, TypeVar
T = TypeVar('T')
class SizedIterable(Generic[T], Iterable[T], Sized):
    pass

这种方式要求类必须实现Iterable和Sized的抽象方法(比如__iter__、__len__),但你实际传入的对象(比如list)并不是这个类的实例,因此会出现类型不兼容错误。而Protocol是结构类型检查,只要对象满足协议定义的方法/属性,就会被视为符合类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 23:30:57