【问题标题】: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 不变。

出了什么问题,我该如何解决?

【问题讨论】:

标签: python list debugging


【解决方案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)

文档


进一步阅读

【讨论】:

    猜你喜欢
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    相关资源
    最近更新 更多