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

列表推导式处理鸭子类型内容时的mypy类型提示问题

问题解答

方法2为什么不报错?

方法2里你给变量d明确标注了List[Union[A, B]]类型,mypy直接复用这个类型信息,遍历d时就清楚每个元素要么是A要么是B,而这两个类都有name属性,所以不会触发报错。

方法1的类型提示为啥没用?

你在方法1里单独声明的c: Union[A, B]是个独立变量,和列表推导式里的循环变量c完全是两回事。推导式里的[A('1'), B('2')]是临时字面量,mypy默认会把这种混合不同类型的列表推断为List[object],遍历它的时候循环变量就被当成object类型,自然找不到name属性。

Python3.8下的解决方案(无需命名临时变量)

方案1:用typing.cast强制指定列表类型

直接给临时列表做类型转换,明确告诉mypy它的真实类型:

from typing import cast, List, Union, Set
from dataclasses import dataclass

@dataclass
class A:
    name: str

@dataclass
class B:
    name: str

f: Set[str] = {c.name for c in cast(List[Union[A, B]], [A('1'), B('2')])}

方案2:用Protocol定义公共接口

因为A和B都有name属性,可以定义一个协议来描述这个共同特性,mypy会自动识别符合协议的类型:

from dataclasses import dataclass
from typing import Protocol, Set

class HasName(Protocol):
    name: str

@dataclass
class A:
    name: str

@dataclass
class B:
    name: str

f: Set[str] = {c.name for c in [A('1'), B('2')]}

这种方式更优雅,不用强制类型转换,后续其他有name属性的类也能复用这个协议。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:46:10