<p>棘手的一点是“同一实例”检查。您可以递归地为整个结构创建一个哈希代码,或者创建一个深度副本并将两者进行比较,但这两种方法都将无法通过“同一实例”检查。你知道吗</p>
<p>您可以创建原始列表的副本,作为以后的参考,但不仅如此:您必须将结构中的每个元素与其原始的<code>id</code>配对:</p>
<pre><code>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
</code></pre>
<p>然后,您可以递归地检查结构并比较所有id<em>和</em>递归地比较任何子结构的内容:</p>
<pre><code>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
</code></pre>
<p>下面是一个示例,以及一些示例修改:</p>
<pre><code>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))
</code></pre>
<p>当然,这两种方法都不完整,必须对其他结构进行扩展,例如<code>dict</code>、<code>set</code>、<code>tuple</code>等。对于<code>set</code>和<code>dict</code>,您可能希望比较<code>sorted</code>条目,但其他条目的性质应该非常相似。你知道吗</p>
<p>请注意,从技术上讲,它不能保证列表不会被修改,例如,在垃圾收集了具有该ID的原始对象之后,ID可以被重用,但是在一般情况下,上述方法应该可以工作。你知道吗</p>