Is there any way to make a list
call a function every time the list is modified?
For example:
>>>l = [1, 2, 3]
>>>def callback():
print "list changed"
>>>apply_callback(l, callback) # Possible?
>>>l.append(4)
list changed
>>>l[0] = 5
list changed
>>>l.pop(0)
list changed
5
I'm almost certain this can't be done with the standard list.
I think the cleanest way would be to write your own class to do this (perhaps inheriting from
list
).You'd have to subclass
list
and modify__setitem__
.As noted in comments, it's more than just
__setitem__
.You might even be better served by building an object that implements the
list
interface and dynamically adds and removes descriptors to and from itself in place of the normal list machinery. Then you can reduce your callback calls to just the descriptor's__get__
,__set__
, and__delete__
.Borrowing from the suggestion by @sr2222, here's my attempt. (I'll use a decorator without the syntactic sugar):
The great thing about this is if you realize you forgot to consider a particular method, it's just 1 line of code to add it. (For example, I forgot
__iadd__
and__imul__
until just now :)EDIT
I've updated the code slightly to be py2k and py3k compatible. Additionally, slicing creates a new object of the same type as the parent. Please feel free to continue poking holes in this recipe so I can make it better. This actually seems like a pretty neat thing to have on hand ...