I have two base classes A
and B
that are defined like this:
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
Class A
holds some management information, whereas class B
holds some other information, which is based on the information contained in class A
, and therefore it knows about it's instance of A
.
I also have two derived classes dA
and dB
that are defined like this:
class dA(A):
def __init__(self, t: B):
self.t = t
class dB(B):
def __init__(self, a: dA):
super(A, self).__init__(a)
These classes (among others (dA1
, dB1
, dA2
, dB2
) ... that are similarly designed) are used for some special operation and therefore they need to store some more information, e.g. the t from the example for this pair of classes, other classes have different stuff to store.
The problem is, that mypy complains about the usage of 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: error: "A" has no attribute "t"
The complain is actually right. A
doesn't have an attribute t
. I also told mypy that B.a
is of type A
, but in this particular case I use dB.a
as of type dA
, which actually has a t, but I explicitly told mypy otherwise.
The questions are:
dB.a
is of type dA
? Do I need to use a TypeVar?I found the question mypy: base class has no attribute x, how to type hint in base class, however, the solution to extend the base class is not feasible, as this would make t
available in all derived classes, not only dA
(what somehow smells bad).
It is possible to ensure that self.a
is of type dA
by using assert:
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")
This assert is recognized by mypy, so that self.a
is known as instance of dA
afterwards and thus has an attribute t
.