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

Python 将元素添加到列表时运行代码,python,list,Python,List,如何在列表中添加内容时进行检测?是否有一个等价于dictionary\uuuuu setitem\uuuuuuuuuuuuuuuuuuuuuu的方法,当通过insert、extend、append或使用+=(\uuuuuuuuuuuuuuuuuuu add)、\uuuuuuud>或其他我可能忘记的方法将某些内容添加到列表中时,将调用该方法?或者我需要一个接一个地挂接这些方法吗?您需要分别覆盖每个方法。特别是您提到的操作性质不同-追加、插入、扩展、以及+=在创建新列表时修改列表 如果你觉得很新奇,

如何在列表中添加内容时进行检测?是否有一个等价于dictionary
\uuuuu setitem\uuuuuuuuuuuuuuuuuuuuuu
的方法,当通过
insert
extend
append
或使用
+=
\uuuuuuuuuuuuuuuuuuu add
)、
\uuuuuuud>或其他我可能忘记的方法将某些内容添加到列表中时,将调用该方法?或者我需要一个接一个地挂接这些方法吗?

您需要分别覆盖每个方法。特别是您提到的操作性质不同-
追加
插入
扩展
、以及
+=
在创建新列表时修改列表

如果你觉得很新奇,这是一种不必写太多样板的潜在方法:

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)

根据要运行的代码访问的内容,您可能需要分别处理
\uuuu添加

正如obskyr的回答所建议的那样,您必须定义
列表的子类
,覆盖许多方法,并仔细测试以确定是否遗漏了某些内容

我的方法使用一个更深的钩子,使用
\uuuu getattribute\uuuuu
(用于方法调用)、
\uuuuu iadd\uuu
(用于
+=
)和
\uuuuuu setitem\uuuuuuu
(用于切片分配)来捕获最大的更改,并调用原始父方法,使其充当一个通用的中间人:

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]
如你所见

  • 列表已正确修改
  • 检测到所有更改

  • 我可能错过了一些访问,但这似乎离我很近。

    +=
    不会创建新列表。@khelwood它确实创建了!然后它将它赋给变量,但它不是同一个对象。我可以看到你会怎么想,但它不是。试试看。@obskyr你把它和字符串或其他不可变对象的
    +=
    混为一谈了。列表是可变的,因此这与
    .extend
    (除此之外,你的答案是最好的ATM:)@Jean-Françoisfar-Huh,你说得对!它没有调用
    extend
    ,但它确实修改了列表。不禁注意到您将成员资格测试从一个集合更改为一个列表-有什么理由不使用集合吗?没有,只是我改进了编辑框中的集合内容,但用+=改进粘贴了我的旧代码。虽然我的需要有点过头了,我喜欢它既聪明又可读。你的需求很重要,但为你的问题提供一个深思熟虑的答案也很重要(对于未来的读者来说,可能要求更高)