Issue
Alright, let's start with the code, because it's pretty explicit :
class c_1:
def __init__(self):
self.a = 5
class c_2:
def __init__(self,other_obj):
self.other = other_obj
self.b = self.other.a
And the output:
obj_1 = c_1()
obj_2 = c_2(obj_1)
print(obj_2.b)
# Output is 5
obj_1.a = 8
print(obj_2.b)
# Output is still 5
This is the problem. I know the second call of obj_2.b should return 5, but I want it to return 8.
I think that what I actually want, is for the value of obj_1.a to be passed by reference for obj_2.b (this example is pretty simple, but in my actual code, there are more attributes from obj_1 that obj_2 uses.)
Is there a way, without calling another method, to automatically update obj_2.b when the value of obj_1.a gets changed ? Thank you.
Solution
It is possible, but your mileage may vary, depending on your use cases:
One approach, shown hereunder, is to implement a Var class
that handles this for you; encapsulating the values inside an object circumvents the 'passing by value', and opens the 'values' to mutability. here is an incomplete (and brittle) example; there are quite a few corner cases to iron out to make it work smoothly, but to answer your question: yes, it is definitely possible:
Other approaches might use the inspect module
, or metaclasses
, or the implementation of callbacks
.
tkinter
in the python standard library uses specialized classes, and a callback approach.
class Var:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, value):
self._value = value
def __repr__(self):
return str(self._value)
class IntVar(Var):
def __iadd__(self, other: int):
self._value = self._value + other
return self.value
class c_1:
def __init__(self):
self._a = IntVar(5)
@property
def a(self):
return self._a
@a.setter
def a(self, value):
self._a.value = value
class c_2:
def __init__(self, other_obj):
self.other = other_obj
self.b = self.other.a
obj_1 = c_1()
obj_2 = c_2(obj_1)
print(obj_2.b)
obj_1.a = 8
print(obj_2.b)
obj_1.a += 2
print(obj_2.b)
Output:
5
8
10
Answered By - Reblochon Masque
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.