gpt4 book ai didi

python - 当子类和父类都满足祖 parent 类型定义时,为什么 mypy 会报告类型不兼容?

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

给出以下代码:

from typing import Tuple


class Grandparent:
items: Tuple[str, ...] = ()


class Parent(Grandparent):
items = ('foo',)


class Child(Parent):
items = ('foo', 'bar')

mypy 报告以下错误:

error: Incompatible types in assignment (expression has type "Tuple[str, str]", base class "Parent" defined the type as "Tuple[str]")

像这样更改代码(在Parent类中再次指定相同的类型)满足mypy:

from typing import Tuple


class Grandparent:
items: Tuple[str, ...] = ()


class Parent(Grandparent):
items: Tuple[str, ...] = ('foo',)


class Child(Parent):
items = ('foo', 'bar')

为什么我需要在类层次结构中的多个位置为 items 重新指定相同的类型,因为所有位置的 items 的分配都满足相同的/原来的定义?有没有办法避免这样做?

最佳答案

我相信这是 mypy 做出的设计选择。简而言之,您问题的关键是:当我们重写某些属性时,我们是要使用与父级相同的类型,还是使用新的重写类型?

Mypy 选择了前者——在许多情况下它可以说更直观。例如,如果我有以下类层次结构:

class Parent:
def foo(self, p1: int) -> None: ...

class Child(Parent):
def foo(self, p1: int, p2: str = "bar") -> None: ...

...Child.foo 的类型为 def (self: Child, p1: int, p2: str = ...) -> None 而不是直接继承 Parent.foo 的类型,即 def (self: Parent, p1 : int) -> None

这样,如果您执行 Child().foo(1, "a"),所有内容仍然会进行类型检查。更广泛地说,允许细化父类型是有用的,唯一的限制是细化后子类型仍然需要遵循里氏替换原则。

如果规则是子定义在方法方面获胜,那么为了保持一致性,对属性应用相同的规则是有意义的。

至于如何解决这个问题——在你看来,我可能会选择继续向每个作业添加类型注释。我不认为这是一个很大的负担。

或者,我可能会考虑将整个类层次结构折叠成一个类,该类接受适当的元组作为 __init__ 中的参数,以尝试避免硬编码某些内容的需要首先。但对于您想要做的任何事情来说,这可能都不是一个可行的解决方案。

关于python - 当子类和父类都满足祖 parent 类型定义时,为什么 mypy 会报告类型不兼容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58377106/

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