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希望成为类变量的字段,因此我不拥有或希望共享现有类层次结构中的内容).但只要我知道这是出于设计,而不是因为我遗漏了什么,就可以添加额外的类型注释。