>> non-6ren">
gpt4 book ai didi

python - 如何检查嵌套容器是否发生变异?

转载 作者:太空宇宙 更新时间:2023-11-04 02:56:41 26 4
gpt4 key购买 nike

我有任意嵌套的容器对象(例如列表和字典)。

我想测试在调用一个函数之后,容器对象是否发生了变化。

>>> x = [[1,2,3], {1,2,3}, "other data", 1]
>>> non_mutating_func(x)
>>> x
[[1,2,3], {1,2,3}, "other data", 1]
>>> mutating_func(x)
>>> x
[[100,2,3], {1,2,3}, "other data", 1] # One of the inner lists got changed. x got mutated.

我还想检查对象身份。这是我所说的检查对象身份的示例:

>>> a = [[1,2],1,2]
>>> def f(x):
... x[0] = [1,2]
...
>>> b = a[0]
>>> f(a)
>>> b is a[0]
False

a[0] 中的列表 [1,2] 已被另一个列表 [1,2] 替换,但列表是不同的对象。所以它算作突变。

注意:以前,对于非嵌套列表,我可以这样做:

x = [1,2,3,4]
x_ori = x[:]
f(x)
mutated = False
if len(x) != len(x_ori):
mutated = True
for i,j in zip(x, x_ori):
if not (i is j):
mutated = True
break

此外,原始容器可能是字典而不是列表。

x = {1:1, "2":"2"}
x_ori = x.copy()
f(x)
mutated = False
if len(x) != len(x_ori):
mutated = True
for k,v in x_ori.items():
if not (k in x):
mutated = True
break
if not (x[k] is v):
mutated = True
break

嵌套容器是否可行?如果是这样,我该怎么做?

最佳答案

棘手的一点是“同一实例”检查。您可以递归地为整个结构创建一个哈希码,或者创建一个深拷贝并比较两者,但两者都将无法通过“同一实例”检查。

您可以创建原始列表的副本,作为以后的引用,但不仅如此:您必须将结构中的每个元素与其原始 id 配对:

def backup(data):
# similar for set, dict, tuples, etc.
if isinstance(data, list):
return id(data), [backup(x) for x in data]
# basic immutable stuff, string, numbers, etc.
return id(data), data

然后,您可以递归地检查结构并比较所有 ID递归地比较任何子结构的内容:

def check(backup, data):
id_, copy = backup
# check whether it's still the same instance
if id_ != id(data):
return False
# similar for set, dict, tuples, etc.
if isinstance(data, list):
return len(data) == len(copy) and all(check(b, d) for b, d in zip(copy, data))
# basic immutable stuff must be equal due to equal ID
return True

这是一个示例,以及一些示例修改:

data = [[1,2,3], [4, [5,6], [7,8]], 9]
b = backup(data)
# data[1][0] = 4 # check -> True, replaced with identical value
# data[1][1] = [5,6] # check -> False, replaced with equal value
# data[1][1].append(10) # check -> False, original value modified
print(check(b, data))

当然,这两种方法都不完整,必须针对其他结构进行扩展,例如dictsettuple等。对于setdict,您可能想要比较 sorted 条目,但除此之外它们在本质上应该非常相似。

请注意,从技术上讲,它不保证列表未被修改,例如在具有该 ID 的原始对象被垃圾回收后,可以重用 ID,但在一般情况下,上述方法应该有效。

关于python - 如何检查嵌套容器是否发生变异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42135867/

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