在鸭子类型内容的列表推导中键入提示 mypy

Type hinting mypy in list comprehension over duck-typed content

提问人:mutableVoid 提问时间:7/28/2023 最后编辑:Daniil FajnbergmutableVoid 更新时间:8/2/2023 访问量:85

问:

我有一个(嵌套的)列表推导式,并收到来自 mypy 的错误。

在我的列表理解中,我正在迭代一个列表,该列表保证仅包含两种类型的实例(不实现相同的基础;在下面的示例中称为 和)。 这两种类型的实例都保证具有我在列表推导中使用的相同属性。Mypy不能自动推断列表的类型,只考虑列表的内容(只有公共基础),因此警告说,该属性未在实例中定义。ABnameobjectsnameobject

我将代码分解为以下示例:

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

@dataclass
class A:
    name: str

@dataclass
class B:
    name: str

# Approach 1:
c: Union[A, B]
f : Set[str] = {c.name for c in [A('1'), B('2')]} # error: "object" has no attribute "name"  [attr-defined]


# Approach 2:
d: List[Union[A, B]] = [A('1'), B('2')]
g : Set[str] = {c.name for c in d} # No issue!

在方法 2 中,mypy 未报告错误。为什么会这样,为什么方法 1 中的类型提示不够?c

可悲的是,在我的实际用例中,该列表只是中间的(没有名称),我无法像方法 2 那样键入提示。有没有办法暗示 mypy 访问实际上是可行的,而无需将列表推导转换为循环?dname

我正在使用python3.8。

python 类型提示 mypy python 类型 duck-typing

评论

1赞 STerliakov 7/28/2023
您是否有权访问 and(它们是否来自您的代码而不是来自某个外部库)?如果是这样,您有一个简单的解决方案AB
0赞 mutableVoid 7/28/2023
不,可悲的是,我无法通过将接口的共享部分移动到共享超类来修改真实。为了解决这个问题并摆脱错误,我现在可以制作一个嵌套的for循环,但更愿意保持列表理解AB
1赞 Daniil Fajnberg 8/2/2023
类型加入类型联合罢工再次...

答: 暂无答案