替换Python列表对象的特殊方法
我想写一个类,这个类是Python列表的子类,并且在列表发生变化时能通知另一个对象。因为有很多方法需要重写,所以我选择了这样的解决方案,而不是重写所有会改变列表的方法:
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)))
这个方法对像“append”这样的普通方法有效,但对于一些特殊方法,比如“__setitem__”,我就直接使用旧的方法了。
我注意到,如果我打印“append”的值,我得到的是类似这样的内容:
<built-in method append of list object at 0x267a7a0>
但是对于“__setitem__”(在普通列表上),我得到的是:
<method-wrapper '__setitem__' of list object at 0x266fd40>
也许这和我的问题有关。
任何帮助都很感激。如果你知道更好的方法来实现我需要做的事情,请分享你的想法。谢谢。
更新: 我还注意到,直接在OwnedList对象上调用“__setitem__”是按预期工作的,但使用方括号就不行。
1 个回答
2
特殊方法只能在对象的类型上定义,而不能在具体的实例上定义来源。
比较一下
>>> class A(object):
... __getitem__ = lambda self,i: 42
>>> A()[0]
42
和
>>> class B(object):
... def __init__(self):
... self.__getitem__ = lambda self,i: 42
>>> B()[0]
TypeError: 'B' object does not support indexing
你应该调整一下 A
,也就是说,要直接在类的主体中定义你的特殊方法,而不是在构造函数里。