I have a class with 3 properties that depend on each other with the following equation: c = a * b
. If any 2 properties are given it should be able to set all 3.
Up to now I came up with the solution below, but I'm pretty sure it can be solved nicer. There is multiple solutions that show how to define dependent properties one way (like here), but I don't see how to extend it to my case, and be able to efficiently set any pair (a,b or b,c or a,c), and calculating the last one. Do I need to maybe look into HasTrait
like here?
My idea below has a prop(**kwargs)
function that always sets all values given any 2 of them. So it should only be called as one of the following three ways: prop(_a = a, _b = b)
, prop(_b = b, _c = c)
, prop(_a = a, _c = c)
with a
, b
, c
any number.
Ideally I'd want to call prop()
with the keys, the name of the actual properties a
, b
, c
instead of _a
, _b
, _c
. In my implementation below it'll not work as the setters for a
, b
, c
call prop()
again and cause an infinite loop.
class Example:
# a * b = c
def __init__(self, **kwargs):
if len(kwargs) == 2: # need to specify at least 2 properties
self.prop(**kwargs)
else:
self._a = self._b = self._c = None
print('Correctly set properties manually using prop function')
def prop(self, **kwargs):
# needs to always set 2 properties out of a, b, c calculate the last one
for key, value in kwargs.items():
setattr(self, key, value)
if '_a' not in kwargs:
self._a = self.c / self.b
elif '_b' not in kwargs:
self._b = self.c / self.a
elif '_c' not in kwargs:
self._c = self.b * self.a
@property
def a(self):
return self._a
@a.setter
def a(self, value):
self.prop(_a = value, _b = self.c / value) # set a holding c constant
@property
def b(self):
return self._b
@b.setter
def b(self, value):
self.prop(_b = value, _a = self.c / value) # set b holding c constant
@property
def c(self):
return self._c
@c.setter
def c(self, value):
self.prop(_c = value, _a = value / self.b) # set c holding b constant