将元素添加到列表时运行代码

时间:2017-06-22 07:54:43

标签: python list

如何检测何时将某些内容添加到列表中?是否存在与字典__setitem__方法等效的方法,当insertextendappend或使用+将某些内容添加到列表时会调用该方法还是+=__add____iadd__),还是我可能忘记的其他一些方法?或者我是否需要逐个挂钩这些方法?

2 个答案:

答案 0 :(得分:4)

您需要单独覆盖每个方法。特别是当您提到的操作性质不同时,appendinsertextend+=会修改列表+创建一个新列表。

如果你感觉很花哨,这是一种可行的方法,而不必写太多样板:

class MyList(list):
    pass

for method in ['append', 'insert', 'extend', '__add__', '__iadd__']:
    def code_added(self, *args, **kwargs):
        # Your code here
        getattr(super(MyList, self), method)(*args, **kwargs)

    setattr(MyList, method, code_added)

根据您要运行访问的代码,您可能需要单独处理__add__

答案 1 :(得分:4)

正如obskyr的回答所暗示的那样,你必须定义一个list的子类并覆盖很多方法,并仔细测试,看看你是否错过了什么。

我的方法使用__getattribute__(对于方法调用)使用更深的钩子,__iadd__(对于+=)和__setitem__(用于切片分配)以捕获最大值更改,并调用原始父方法,使其像通用中间人一样:

class MyList(list):
    def __getattribute__(self,a):
        if a in {"append","extend","remove","insert","pop","reverse","sort","clear"}:
            print("modification by {}".format(a))
        else:
            print("not modified {}".format(a))
        return list.__getattribute__(self,a)

    def __iadd__(self,v):
        print("in place add")
        return list.__iadd__(self,v)

    def __setitem__(self,i,v):
        print("setitem {},{}".format(i,v))
        return list.__setitem__(self,i,v)

l = MyList()

l.append(12)
l.extend([12])
l.remove(12)
print(l)
l[:] = [4,5,6]
l += [5]
print(l)

输出:

modification by append
modification by extend
modification by remove
[12]
setitem slice(None, None, None),[4, 5, 6]
in place add
[4, 5, 6, 5]

如你所见

  1. 列表已正确修改
  2. 检测到所有更改
  3. 我可能错过了一些访问,但这似乎非常接近我。