通过旧列表修改列表副本的错误
Posted
技术标签:
【中文标题】通过旧列表修改列表副本的错误【英文标题】:Bug where copy of a list is being modified through the old one 【发布时间】:2016-01-08 17:22:23 【问题描述】:我在 python 中处理矩阵,花了几个小时尝试调试程序后,设法将问题本质上追溯到这段代码,其中矩阵的所有非零条目都均匀增加。
list2=[[1,2],[0,4]]
list1=list2
for row in list1:
for i in range(0,len(row)):
if row[i]!=0:
row[i]=row[i]+10
print(list1) #returns [[11,12],[0,14]], as expected
print(list2) #returns [[11,12],[0,14]], want to return [[1,2],[0,4]]
这里缺少一些基本的东西。我认为通过声明 list1=list2
创建了一个新列表,其余代码对其进行了修改,同时保持 list2
不变。
出了什么问题,我该如何解决?
【问题讨论】:
从拷贝导入深拷贝; list1=deepcopy(list2) Immutable vs mutable types - Python的可能重复 【参考方案1】:这段代码:
list2=[[1,2],[0,4]]
list1=list2
不会在list1
中创建一个新列表,它只是将名称list1
绑定到与list2
相同的对象。因此,通过名称 list2
对列表所做的任何更改也将通过 list1
可见。
您可以使用copy
模块:
import copy
list2 = [[1,2],[0,4]]
list1 = copy.deepcopy(list2)
list1
现在将引用list2
的副本,对列表的更改将仅通过list2
反映。
对于包含更复杂对象的列表,例如其他列表,copy.deepcopy()
将递归复制嵌套对象。
【讨论】:
我刚刚尝试了这个更改,但它仍然为两者返回[[11,12],[0,14]]
。
list1 = list2[:]
是浅拷贝
太棒了,我永远不会接受这个。大学里有一整门关于python的课程,没有提到任何阶段。【参考方案2】:
问题;您没有复制实际列表
通过list1 = list2
,您只是将句柄复制到list1
所指的列表中,为了提供实际副本,您必须明确说明这是您想要的.
示例
a = [1,2,3];
b = a
c = list(a) # create a new list, copying the elements in `a`
d = a[:] # equivalent to `list(a)` (with a slightly weird syntax)
a[1] = 99
c[1] = 0
print (a) # [1,99,3]
print (b) # [1,99,3]
print (c) # [1,0,3]
print (d) # [1,2,3]
解决方案;一直向下复制
您遇到的问题将出现在另一个位置,因为您在 list 中有 lists。为了一次性制作一个深副本,建议使用copy.deepcopy,如下例所示。
import copy
list1 = copy.deepcopy (list2)
文档
docs.python.org - 8.17. copy — Shallow and deep copy operations进一步阅读
How to clone or copy a list in Python? What is the best way to copy a list? Deep copy a list in Python【讨论】:
以上是关于通过旧列表修改列表副本的错误的主要内容,如果未能解决你的问题,请参考以下文章