深度复制与列表理解
Deep copy vs. List Comprehension
我对编程比较陌生,我一直在理解一些东西,这似乎是 Python 中克隆对象的基础知识。
假设我们有以下代码但没有使用 deepcopy 模块:
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = [x for x in nested_list]
现在如果我们做类似的事情:
copy[1] = [9999999]
然后它将return以下内容:
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = [[1, 2, 3], [9999999], [7, 8, 9]]
但是,如果我们只修改其中一个嵌套列表中的单个元素,例如:
copy[0][1] = 9999999
那么原始变量和副本变量都会return相同的值:
nested_list = [[1, 9999999, 3], [4, 5, 6], [7, 8, 9]]
copy = [[1, 9999999, 3], [4, 5, 6], [7, 8, 9]]
为什么当我们给嵌套列表一个新值时它工作得很好,但是当我们给嵌套列表中的一个项目一个新值时,它也会改变原来的值?在变量 nested_list 和 copy 上调用 id() 函数表明它们是独立的对象,至少从我的理解来看是这样。
例如:
copy = nested_list # copy and nested_list share the same id()
copy = [x for x in nested_list] # now they have different id()
copy = deepcopy(nested_list) # again they have different id()
我知道另一种解决方案是深度复制功能,但是由于它非常慢,我想知道是否还有其他解决方案?
在此先感谢大家!
copy = [x for x in nested_list]
发生的灰黄色副本正在创建一个新的副本对象,其 id()
与 nested_list
不同,但其中的所有嵌套列表都具有相同的 id两个列表中的列表。
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = [x for x in nested_list]
print(id(copy)) #54769064
print(id(nested_list)) #54546184
print([id(i) for i in copy]) #[58832096, 58831816, 58619384]
print([id(i) for i in nested_list]) #[58832096, 58831816, 58619384]
进行深度复制时 copy = deepcopy(nested_list)
复制嵌套列表,同时创建具有新 ID 的新列表,当将新值分配给其中一个嵌套列表时,如 copy[0][1] = 9999999
将仅更改复制第一个列表项目而不是 nested_list[0][1]
值。
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = deepcopy(nested_list)
copy[0][1] = 9999999
print(copy) #[[1, 9999999, 3], [4, 5, 6], [7, 8, 9]]
print(nested_list) #[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy
和 nested_list
的子列表在内存中的相同位置。并且所有相应的子列表都具有相同的 id。这就是为什么你有这种行为。
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = [x for x in nested_list]
print(id(copy[0]) == id(nested_list[0])) #True
print(id(copy) == id(nested_list)) #False
如果您提前知道要更改的sublists
,那么可以只对该子列表进行深度复制,以加快性能。
我不知道您使用的是哪种编程语言,但变量引用在 python 中的工作方式不同。我建议您阅读这篇清楚说明的文章。
https://www.python-course.eu/python3_deep_copy.php
我还写了一篇关于变量引用的Medium post。你可以看看。
基本上,当你有一个列表列表时会发生什么,然后做
copy[1] = [9999999]
实际上是在更改第一级引用。但是当你像
这样深入时
copy[0][1] = 9999999
那么您正在比尚未复制的参考更深层次地更改元素。把它想象成一棵树。复制功能就像一个浅拷贝,当你执行浅拷贝时,你只是复制并制作另一个第一个引用的对象。但是第2、第3以后还是一样。
我对编程比较陌生,我一直在理解一些东西,这似乎是 Python 中克隆对象的基础知识。
假设我们有以下代码但没有使用 deepcopy 模块:
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = [x for x in nested_list]
现在如果我们做类似的事情:
copy[1] = [9999999]
然后它将return以下内容:
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = [[1, 2, 3], [9999999], [7, 8, 9]]
但是,如果我们只修改其中一个嵌套列表中的单个元素,例如:
copy[0][1] = 9999999
那么原始变量和副本变量都会return相同的值:
nested_list = [[1, 9999999, 3], [4, 5, 6], [7, 8, 9]]
copy = [[1, 9999999, 3], [4, 5, 6], [7, 8, 9]]
为什么当我们给嵌套列表一个新值时它工作得很好,但是当我们给嵌套列表中的一个项目一个新值时,它也会改变原来的值?在变量 nested_list 和 copy 上调用 id() 函数表明它们是独立的对象,至少从我的理解来看是这样。
例如:
copy = nested_list # copy and nested_list share the same id()
copy = [x for x in nested_list] # now they have different id()
copy = deepcopy(nested_list) # again they have different id()
我知道另一种解决方案是深度复制功能,但是由于它非常慢,我想知道是否还有其他解决方案?
在此先感谢大家!
copy = [x for x in nested_list]
发生的灰黄色副本正在创建一个新的副本对象,其 id()
与 nested_list
不同,但其中的所有嵌套列表都具有相同的 id两个列表中的列表。
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = [x for x in nested_list]
print(id(copy)) #54769064
print(id(nested_list)) #54546184
print([id(i) for i in copy]) #[58832096, 58831816, 58619384]
print([id(i) for i in nested_list]) #[58832096, 58831816, 58619384]
进行深度复制时 copy = deepcopy(nested_list)
复制嵌套列表,同时创建具有新 ID 的新列表,当将新值分配给其中一个嵌套列表时,如 copy[0][1] = 9999999
将仅更改复制第一个列表项目而不是 nested_list[0][1]
值。
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = deepcopy(nested_list)
copy[0][1] = 9999999
print(copy) #[[1, 9999999, 3], [4, 5, 6], [7, 8, 9]]
print(nested_list) #[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy
和 nested_list
的子列表在内存中的相同位置。并且所有相应的子列表都具有相同的 id。这就是为什么你有这种行为。
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = [x for x in nested_list]
print(id(copy[0]) == id(nested_list[0])) #True
print(id(copy) == id(nested_list)) #False
如果您提前知道要更改的sublists
,那么可以只对该子列表进行深度复制,以加快性能。
我不知道您使用的是哪种编程语言,但变量引用在 python 中的工作方式不同。我建议您阅读这篇清楚说明的文章。 https://www.python-course.eu/python3_deep_copy.php
我还写了一篇关于变量引用的Medium post。你可以看看。
基本上,当你有一个列表列表时会发生什么,然后做
copy[1] = [9999999]
实际上是在更改第一级引用。但是当你像
这样深入时copy[0][1] = 9999999
那么您正在比尚未复制的参考更深层次地更改元素。把它想象成一棵树。复制功能就像一个浅拷贝,当你执行浅拷贝时,你只是复制并制作另一个第一个引用的对象。但是第2、第3以后还是一样。