Reputation: 13254
In case you want to change other variables in a class on change
of an attribute you simply just write a property
for it. That works fine, if you have a simple data type. But if your variable contains a complex type like a list (not so untypical), the content itself can be changed without calling the variable.setter
again.
Are there any callbacks or events that can be used to track changes to a list attribute of a class? What else can be done to keep the code clean and not destroy the inner functionality of the class?
Example:
class Accumulator(object)
def __init__(self,all_things):
# :param all_things: a list of stuff of any kind
self.__all_things = all_things
@property
def all_things(self):
return self.__all_things
@all_things.setter
def all_things(self,input):
self.__all_things = input
Thinking outside the box is probably the solution. The priority is not to keep the class structure alive, but to find a pattern that works and allows a clean API!
Upvotes: 1
Views: 83
Reputation: 13254
To allow discussion and increase creativity I want to offer the following solution myself:
class Accumulator(object):
def __init__(self,all_things):
#:param all_things: a sequence or generator of stuff of any kind
self.__all_things = tuple(all_things)
@property
def all_things(self):
return self.__all_things
@property
def all_things(self, all_things):
self.__all_things = tuple(all_things)
It's clean, it's read-only and nothing can go wrong or be misused. Now the same assumption applies as in the question's structure: You need to reset it, if you want to change it. But you don't have to tell the user, because it's his only chance. If the user still wonders why, he can read the hopefully verbose class docstring.
Upvotes: 1
Reputation: 1122152
You would have to use a custom subclass of list to detect changes:
class MyList(list):
on_change_callback = None
def _notify(self):
if self.on_change_callback is not None:
self.on_change_callback(self)
def __setitem__(self, index, value):
super(MyList, self).__setitem__(self, index, value)
self._notify()
# Etc, each mutating method needs to be overridden.
You'd need to override each mutating method, call the original method (through super()
), then call self._notify()
. For a list of methods, see the Emulating container types section.
Upvotes: 2