python - mypy 抱怨扩展基类的属性类型
问题描述
我有两个基类A
,B
它们的定义如下:
class A(object):
def common_function(self):
pass
class B(object):
def __init__(self, a: A):
self.a = a
def another_common_function(self):
pass
ClassA
持有一些管理信息,而 classB
持有一些其他信息,这些信息基于 class 中包含的信息A
,因此它知道它的实例A
。
我还有两个派生类dA
,dB
它们的定义如下:
class dA(A):
def __init__(self, t: B):
self.t = t
class dB(B):
def __init__(self, a: dA):
super(A, self).__init__(a)
这些类(以及其他类似设计的 ( dA1
, dB1
, dA2
, dB2
) ...)用于某些特殊操作,因此它们需要存储更多信息,例如这对类的示例中的 t ,其他类有不同的要存储的东西。
问题是,mypy 抱怨使用dB.a.t
:
class dB(B):
def __init__(self, a: dA):
super(A, self).__init__(a)
def do(self):
if self.a.t is None:
print("something")
test.py:错误:“A”没有属性“t”
抱怨其实是对的。A
没有属性t
。我还告诉 mypy that B.a
is of type A
,但在这种特殊情况下,我使用dB.a
as of type dA
,它实际上有 at ,但我明确告诉 mypy 否则。
问题是:
- 这是否违反了 Liskov 原则?
- 如果不是 1,有没有办法告诉 mypy 在这种特殊情况下
dB.a
是 typedA
?我需要使用 TypeVar 吗? - 如果是 1,有没有办法重组类以不违反 Liskov 原则以及让类型检查器能够识别正确的类型?
我发现了问题mypy: base class has no attribute x, how to type hint in base class,但是,扩展基类的解决方案是不可行的,因为这将t
在所有派生类中都可用,不仅dA
(有什么味道坏的)。
解决方案
可以使用 assert来确保它self.a
的类型:dA
class dB(B):
def __init__(self, a: dA):
super(A, self).__init__(a)
def do(self):
assert isinstance(self.a, dA)
if self.a.t is None:
print("something")
这个断言被 mypy 识别,因此self.a
被称为dA
之后的实例,因此具有一个属性t
。
推荐阅读
- vue.js - 在 Vue 应用程序中的何处放置代码以在应用程序初始加载时提取数据
- typescript - 在 DB 中获取一个 id 数组,$lookup 到另一个具有相同 id 的集合,并通过 id 投影数据 - mongoose 与 TS
- ruby-on-rails - 在多个地方使用刺激控制器
- bash - 将变量从主脚本转移到从第一个脚本开始的不同 shell
- javascript - Vue排序数组后跟索引(0、1、2、3 ...)
- tensorflow - ImageDataGenerator 是如何工作的?
- jquery - 如何同时使用 Select2 作为可搜索的下拉菜单或文本框?
- python - 使用 super() 从多个类函数继承变量
- pyspark - 调用 o111.pyWriteDynamicFrame 时出错。awaitResult 中抛出的异常:
- python - 如何使用 Keras(增强、拆分)预处理我的 ImageDataset