Replacing special methods of a Python list object
I want to write a class that subclasses the Python list and notifies a certain other object when the list changes. Since there are many methods that need to be overridden, I opted for a solution like this, instead of overriding all methods that change the list:
destructiveMethods = ["__setitem__",
"__setslice__",
"__delitem__",
"__delslice__",
"append",
"extend",
"remove",
"reverse",
"sort"]
class OwnedList(list):
def __init__(self, owner, initValue=[]):
super(OwnedList, self).__init__(initValue)
def wrappedMethod(method):
def resultMethod(*args, **kwargs):
ret = method(*args, **kwargs)
self.owner.notify()
return ret
return resultMethod
self.owner = owner
for m in destructiveMethods:
setattr(self, m, wrappedMethod(getattr(self, m)))
This works for methods like "append" but not for special methods like "__setitem__". For those, I simply get the old methods.
I've noticed that if I print the value of, say, append, I get something like:
<built-in method append of list object at 0x267a7a0>
But for __setitem__ (on a vanilla list) this is what I get:
<method-wrapper '__setitem__' of list object at开发者_开发知识库 0x266fd40>
Maybe that has something to do with my problem.
Any help is appreciated. If you know a better way of accomplishing what I need to do, please share your ideas on that as well. Thanks.
UPDATE: Something else I've noticed is calling __setitem__ directly on an OwnedList object works as expected, but using brackets does not.
Special methods can only defined on the object's type and not on instancessource.
Compare
>>> class A(object):
... __getitem__ = lambda self,i: 42
>>> A()[0]
42
and
>>> class B(object):
... def __init__(self):
... self.__getitem__ = lambda self,i: 42
>>> B()[0]
TypeError: 'B' object does not support indexing
You should adapt A
, i.e. define your special methods directly in the class body and not in the constructor.
精彩评论