Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当子类和父类都满足祖父母类型定义时,为什么mypy报告不兼容的类型?_Python_Mypy_Python Typing - Fatal编程技术网

Python 当子类和父类都满足祖父母类型定义时,为什么mypy报告不兼容的类型?

Python 当子类和父类都满足祖父母类型定义时,为什么mypy报告不兼容的类型?,python,mypy,python-typing,Python,Mypy,Python Typing,给定以下代码: 从键入导入元组 班级祖父母: 项目:元组[str,…]=() 班级家长(祖父母): 项目=('foo',) 班级儿童(家长): 项目=('foo','bar') mypy报告以下错误: error: Incompatible types in assignment (expression has type "Tuple[str, str]", base class "Parent" defined the type as "Tuple[str]") 这样更改代码(在父类中再次

给定以下代码:

从键入导入元组
班级祖父母:
项目:元组[str,…]=()
班级家长(祖父母):
项目=('foo',)
班级儿童(家长):
项目=('foo','bar')
mypy
报告以下错误:

error: Incompatible types in assignment (expression has type "Tuple[str, str]", base class "Parent" defined the type as "Tuple[str]")
这样更改代码(在
父类中再次指定相同类型)满足
mypy

从键入导入元组
班级祖父母:
项目:元组[str,…]=()
班级家长(祖父母):
项目:元组[str,…]=('foo',)
班级儿童(家长):
项目=('foo','bar')

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

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

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

类父级:
def foo(self,p1:int)->None:。。。
班级儿童(家长):
def foo(self,p1:int,p2:str=“bar”)->无:。。。
…对于
Child.foo
来说,有一个类型为
def(self:Child,p1:int,p2:str=…)->None
而不是直接继承
Parent.foo
,即
def(self:Parent,p1:int)->None

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

如果规则是子定义对方法有利,那么为了一致性起见,将相同的规则应用于属性是有意义的

至于如何解决这个问题——以您的角度来看,我可能会满足于继续向每个赋值添加类型注释。我不认为这是一个很大的负担


或者,我可以考虑将整个类层次结构折叠成一个类,该类接受适当的元组作为
\uuuuu init\uuuuuu
中的参数,以避免硬编码的需要。但是,无论你想做什么,这可能都不是一个可行的解决方案。

这真的很有趣,也很有意义——谢谢。在这种情况下,调整类层次结构或将
传递到
\uuuuu init\uuuu
(我遇到的真正的类实际上是Django admin类,其中包括各种混合,而
是Django希望成为类变量的
字段,因此我不拥有或希望共享现有类层次结构中的内容).但只要我知道这是出于设计,而不是因为我遗漏了什么,就可以添加额外的类型注释。