mypy抱怨扩展基类的属性类型

时间:2019-06-06 14:11:13

标签: python derived-class typechecking mypy

我有两个基类AB定义如下:

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

A保存一些管理信息,而类B保存一些其他信息,这些信息基于类A中包含的信息,因此它知道它是{的实例{1}}。

我还必须派生如下定义的类AdA

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) dA1dB1dA2)用于某些特殊操作,因此它们需要存储更多信息,例如这对类的示例中的t,其他类要存储不同的东西。

问题是,mypy抱怨使用dB2

dB.a.t
  

test.py:错误:“ 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") 没有属性A。我还告诉mypy t的类型为B.a,但是在这种情况下,我使用A的类型为dB.a,实际上它是at,但是我明确地告诉mypy否则。

问题是:

  1. 这是否违反了Liskov原则?
  2. 如果不为1,是否有办法告诉mypy,在这种特殊情况下,dA的类型为dB.a?我需要使用TypeVar吗?
  3. 如果为1,是否有一种方法可以重组类而不违反Liskov原则,并且类型检查器能够识别正确的类型?

我发现了问题mypy: base class has no attribute x, how to type hint in base class,但是扩展基类的解决方案不可行,因为这会使dA在所有派生类中可用,而不仅是t(闻起来很难闻。

1 个答案:

答案 0 :(得分:0)

可以通过使用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