gpt4 book ai didi

python - mypy:创建一个接受子类实例列表的类型

转载 作者:行者123 更新时间:2023-12-01 12:09:26 25 4
gpt4 key购买 nike

假设我有一个 Child作为 Parent 子类的类类和一个接受 Parent 的实例列表的函数子类:

from typing import List


class Parent:
pass


class Child(Parent):
pass


def func(objects: List[Parent]) -> None:
print(objects)


children = [Child()]
func(children)

运行 mypy这会产生一个错误:
 error: Argument 1 to "func" has incompatible type "List[Child]"; expected "List[Parent]"

我如何为此创建一个类型?

附言有一种方法可以使用 Sequence 来修复此特定错误。类型:
def func(objects: Sequence[Parent]) -> None:
print(objects)

但这在其他类似情况下无济于事。我需要一个 List ,而不是 Sequence .

最佳答案

在这里传入一个列表基本上不是类型安全的。例如,如果你这样做会怎样?

def func(objects: List[Parent]) -> None:
print(objects)
objects.append(Parent())

children: List[Child] = [Child(), Child(), Child()]
func(children)
# Uh-oh! 'children' contains a Parent()!

如果允许进行类型检查,您的代码最终将包含错误。

要使用类型术语, List有意设计为不变类型。也就是说,即使 ChildParent 的子类, List[Child] 并非如此是 List[Parent] 的子类型, 或相反亦然。您可以找到有关不变性的更多信息 herehere .

最常见的替代方法是使用 Sequence相反,这是一个只读接口(interface)/协议(protocol)/任何东西。而且由于 Sequence 是只读的,因此它是协变的是安全的:即 Sequence[Child]被认为是 Sequence[Parent] 的有效子类型.

根据您的具体操作,您可以使用 type variables反而。例如。而不是说“这个函数接受一个父列表”,你说“这个函数接受一个任何父类的列表,或者父类的子类”:
TParent = TypeVar('TParent', bound=Parent)

def func(objects: List[TParent]) -> List[TParent]:
print(objects)

# Would not typecheck: we can't assume 'objects' will be a List[Parent]
objects.append(Parent())

return objects

根据您的具体操作,您可以创建一个 custom Protocol它定义了一个只写的类似列表的集合(或自定义数据结构)。由于你的数据结构是只写的,你可以使它成为逆变的——即 WriteOnlyThing[Parent]将是 WriteOnlyThing[Child] 的子类型.然后你制作 func接受 WriteOnlyThing[Child]并且可以安全通过 WriteOnlyThing[Child]WriteOnlyThing[Parent] .

如果这两种方法都不适用于您的情况,您唯一的办法是使用 # type: ignore要消除错误(不推荐),放弃对列表内容进行类型检查,并使用类型为 List[Any] 的参数(也不推荐),或者弄清楚如何重组代码,使其类型安全。

关于python - mypy:创建一个接受子类实例列表的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53275080/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com