Well, as other people have pointed out already, the problem comes down to the fact that you're dealing with imutable objects. Having realized that, you should either use a mutable type, or use a callback to manage updates. Adriano Abrantes gave an example of an alternative using mutable types, but if that's not what you're looking for, here's an example of potential callback system:
# bad habit to be using the old style class definition (i.e. `class Foo:`)
# the `@property` decorator wont work if you use the old style
class Sync(object):
def __init__(self, name, value, *dependants):
"""Sync the attribute `name` on all `dependants` when `self.value` is updated"""
self._name = name
self._value = value
self._updating = False
self._dependants = list(dependants)
self._update_dependants()
@property
def value(self):
return self._value
@value.setter
def value(self, x):
if x != self._value:
self._value = x
self._update_dependants()
def _update_dependants(self):
self._updating = True
for d in self._dependants:
if getattr(d, self._name) != self.value:
if isinstance(d, Sync):
if not d._updating:
setattr(d, self._name, self.value)
else:
setattr(d, self._name, self.value)
self._updating = False
def add_dependant(self, other):
self._dependants.append(other)
self._update_dependants()
def del_dependnant(self, other):
self._dependants.remove(other)
def __repr__(self):
return "Sync('"+self._name+"': "+repr(self.value)+")"
def __eq__(self, other):
if isinstance(other, Sync):
return self.value == other.value
else:
return self.value == other
def __ne__(self, other):
return not self.__eq__(other)
s1 = Sync('value', 2)
s2 = Sync('value', 1)
print('setup the Sync objects:')
print('>>> ' + repr(s1) + (' == ' if s1 == s2 else ' != ') + repr(s2))
s1.add_dependant(s2)
s2.add_dependant(s1)
print('add sync objects as dependants of each other:')
print('>>> ' + repr(s1) + (' == ' if s1 == s2 else ' != ') + repr(s2))
s1.value += 1
print('check that value changes transfer from one to the other:')
print('>>> ' + repr(s1) + (' == ' if s1 == s2 else ' != ') + repr(s2))
If this still doesn't satisfy you, I'd look into something called Traitlets. It's a package from Ipython that's part of Project Jupyter which enforces type checking, streamlines callback systems, and makes app configuration easy. I've been contributing to the project for a while, so if you have any questions about Traitlets feel free to ask me here or post them on Gitter and the dev team will answer them.