开发者

Replacing special methods of a Python list object

开发者 https://www.devze.com 2023-03-06 05:28 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消