Is it possible to initialize instances of classes with attributes that are dependent across (not in circular way)?
Today, I use dictionaries instead of classes as follows:
dictA = {'A1': 10}
dictB = {'B1': 2}
dictB['B2'] = dictA['A1'] * dictB['B1']
dictA['A2'] = dictB['B2'] * 3 # dictA['A1'] * dictB['B1'] * 3
print(dictA) # {'A1': 10, 'A2': 60}
print(dictB) # {'B1': 2, 'B2': 20}
When I try to express the above with classes, I end up with RecursionError: maximum recursion depth exceeded
.
class A:
def __init__(self):
self.A1 = 10
self.A2 = B().B2 * 3
class B:
def __init__(self):
self.B1 = 2
self.B2 = self.B1 * A().A1
a = A()
b = B()
The dictionaries (classes) are separate because they represent different types of data (e.g. employees and time).
CodePudding user response:
You need to make the initializers non-circular. Then you can use @property
to lazily evaluate the properties
class A:
def __init__(self):
self.A1 = 10
@property
def A2(self):
return B().B2 * 3
class B:
def __init__(self):
self.B1 = 2
@property
def B2(self):
return self.B1 * A().A1
a = A()
b = B()
print(a.A1, a.A2, b.B1, b.B2)
Result:
10 60 2 20
CodePudding user response:
Another alternative:
class A:
def __init__(self):
self.A1 = 10
def add_A2(self, x):
self.A2 = x.B2 * 3
class B:
def __init__(self):
self.B1 = 2
def add_B2(self, x):
self.B2 = self.B1 * x.A1
a = A()
b = B()
b.add_B2(a)
a.add_A2(b)
CodePudding user response:
You get a RecursionError
because you create an instance of B
to set A2
, and to create an instance of B
you need to create an instance of A
to set B2
. You will keep creating instances of A
and B
in a circular manner.
You can declare class attributes, which can be used without creating an instance of the class. Note that this value is always the same for all instances of a class. So you can use it for a value like days_of_week = 7
, but not for a persons age age = 34
, as a persons age is not always 34.
Assuming A1
and A2
can be class attributes, which are always the same, you could do the following:
class A:
A1 = 10
def __init__(self):
self.A2 = B.B1 * self.A1 * 3
class B:
B1 = 2
def __init__(self):
self.B2 = self.B1 * A.A1
a = A()
b = B()
print(a.A1, a.A2)
print(b.B1, b.B2)