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

问题描述 投票:0回答:2

我有两个基类

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

A
保存一些管理信息,而类
B
保存一些其他信息,这些信息基于类
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
B.a
A
类型,但在这种特殊情况下,我使用
dB.a
作为
dA
类型,它实际上有一个 t,但我明确告诉 mypy 否则。

问题是:

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

我发现了问题mypy:基类没有属性x,如何在基类中键入提示,但是,扩展基类的解决方案是不可行的,因为这将使

t
在所有派生类中可用,不仅是
dA
(不知何故闻起来很难闻)。

python python-typing mypy derived-class
2个回答
1
投票

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


0
投票

在此实例中,您可以通过执行以下操作来指定

self.a
的类型;

class dB(B):
    a: dA

    ...  # Rest as before

应该指出的是,我无法复制OP提供的代码,因为

mypy
抱怨
super
dB
的第二个参数与参数1不是同一实例。尽管如此,这应该对你有用,就像我在类似的情况下一样。

© www.soinside.com 2019 - 2024. All rights reserved.