gpt4 book ai didi

python - 如何检测嵌套列表的哪些元素发生了变化? (Python)

转载 作者:太空宇宙 更新时间:2023-11-03 11:51:22 26 4
gpt4 key购买 nike

我有一个大型 2D(列表的列表)列表,每个元素都包含一个整数、字符串和字典的列表。我希望能够确定任何被修改元素的“路径”(例如 [2][3][2]["items"][2] 最坏的情况!),并在修改时触发.这个列表太大了,浏览一下看看有什么变化!理想情况下,我还想要新元素的副本,尽管稍后可以找到。

我的第一次尝试是创建一个类,并覆盖它的 __setattr__ 方法:

class Notify():
def __setattr__(self, name, value):
self.__dict__[name] = value #Actually assign the value
print name, value #This will tell us when it fires

但是,__setattr__ 方法只在设置一个不被索引(或键)访问的变量时触发,因为这似乎将调用外包给包含的 list()/dict()类(class)不是我们类(class)。

>>> test = Notify()
>>> test.var = 1 #This is detected
var 1

>>> test.var = [1,2,3] #Now let's set it to a list
var [1, 2, 3]

>>> test.var[0] = 12 #But when we assign a value via an index, it doesn't fire
>>> test.var
[12, 2, 3] #However it still assigns the value, so it must be talking to the list itself!

所以,总而言之,我想要(实际上是任何方法)告诉我什么(索引/键列表)发生了变化,并且这需要在发生时发生,因为扫描整个过程太昂贵了列表。我也不能依赖修改列表的代码来提供详细信息。如果这对于第 n 个嵌套列表是不可能的,我可以使用只给出前两个索引的东西,因为那里的数据不会太大而无法扫描。预先感谢您的帮助!

编辑:尽管这个问题 Track changes to lists and dictionaries in python? 仍然没有喜悦似乎接近我所需要的。不幸的是,我的类(class)不是很好,需要其他人的帮助!

编辑:看过这个Python: Right way to extend list让我想到继承 list 可能不是一个好主意。我改用代理类提出了以下代码。然而,最初的问题仍然存在,即对嵌套列表的修改不会记录下来。类组合而不是继承是个好主意吗?

from UserList import UserList

class NotifyList(UserList):

def __init__(self, initlist=None):
self.data = []
if initlist is not None:
if type(initlist) is list:
self.data[:] = initlist
elif isinstance(initlist, NotifyList):
self.data[:] = initlist.data[:]
else:
self.data = list(initlist)

def __setitem__(self, key, item):
if type(item) is list:
self.data[key] = NotifyList(item)
else:
self.data[key] = item
print key, item

def append(self, item):
if type(item) is list:
self.data.append(NotifyList(item))
else:
self.data.append(item)
print self.index(item), item

最佳答案

您需要在可跟踪列表的(可跟踪)列表中创建一个报告链,其中每个列表都向其父级报告修改。在您的 NotifyList 类中,向构造函数添加父级参数和 ID 参数,父级将通过该 ID 知道新项目——当父级是列表时,这将是一个列表索引:

class NotifyList(UserList):
def __init__(self, inilist=None, parent=None, id=None):
self.parent = parent
self.id = id
# remainder of __init__()...

当发生修改时,应该通知家长。例如在 __setitem__ 中:

def __setitem__(self, key, item):
if type(item) is list:
self.data[key] = NotifyList(item, self, str(key)) # Don't forget the new item's parent
else:
self.data[key] = item
self.alertParent(str(key), str(item)) # Report up the chain instead of printing

alertParent() 是:

def alertParent(self, key, item):
strChange = "[{0}] = {1}".format(key, item)
self.parent.notifyChange(self.id, strChange)

notifyChange() 是如何工作的?

def notifyChange(self, childKey, strChangeInChild):
strChange = "[{0}]{1}".format(childKey, strChangeInChild)
self.parent.notifyChange(self.id, strChange)

它只是将通知向上传播,将自己的 ID 添加到消息中。

唯一缺失的环节是,报告链的顶端发生了什么?最后应该打印更改消息。这是通过重用 alertParent() 来完成此操作的简单技巧:

def alertParent(self, key, item):
if self.parent is None: # I am the root
print "[{0}]{1}".format(key, item)
else:
# remainder of alertParent() shown above...
...
def notifyChange(self, childKey, strChangeInChild):
if self.parent is None: # I am the root
self.alertParent(childKey, strChangeInChild) # Actually just prints a change msg
else:
# remainder of notifyChange() shown above...

我把它编码了,完整版本可用here [Google Doc](关于我上面介绍的内容,有几个小错误修复)。在行动中:

>>> from test import NotifyList
>>> top = NotifyList([0]*3, None, None) # Now we have [0 0 0]
>>> print top
NList-[0, 0, 0]

>>> top[0] = NotifyList([0]*3, top, 0) # Now we have [ [0 0 0] 0 0 ]
[0] = NList-[0, 0, 0] #-------------- The tracking msg is fired

>>> print top
NList-[<test.NotifyList object at 0x0000000002163320>, 0, 0]

>>> top[0][1] = NotifyList([0]*3, top[0], 1) # Now we have [ [[0 0 0] 0 0] 0 0 ]
[0][1] = NList-[0, 0, 0] #----------- The tracking msg fired again

>>> top[0][1][2] = "this is a string" # Now we have [ [[0 0 "this is a string] 0 0] 0 0 ]
[0][1][2] = this is a string #------- And another tracking msg

>>> print top[0][1][2]
this is a string

>>> print top[0][1]
NList-[0, 0, 'this is a string']

关于python - 如何检测嵌套列表的哪些元素发生了变化? (Python),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26607960/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com