【问题标题】:Overwriting a list in a two for loop function (Python)在两个 for 循环函数中覆盖列表(Python)
【发布时间】:2015-08-06 17:57:03
【问题描述】:

所以让我们考虑一下我有以下数组:

arr1 = [[1,1],[2,1]]

现在,我构造如下函数:

def func(mylist):                                                                                                                                             
    print(mylist)                                                                                                                                             
    List = list(mylist)                                                                                                                                       
    for i in range(2):                                                                                                                                        
        for j in range(2):                                                                                                                                    
            List[i][j]=0                                                                                                                                      
    print mylist                                                                                                                                              
    print List                                                                                                                                                
    return mylist            

然后,当我在我的 arr1 上调用我的函数时,初始数组被修改(mylist)。 这真是奇怪的行为,因为我正在做一个 mylist 的副本,而且只有 修改复制的数组列表。任何人都可以向我解释发生了什么?

【问题讨论】:

  • list() 只创建浅拷贝,使用copy.deepcopy
  • 你的缩进和命名无处不在
  • @Ashwini Chaudhary 好的,谢谢。这解决了问题。抱歉这个愚蠢的问题。
  • 我不知道为什么人们对这个投票如此激烈,SO 上的格式对新手来说并不那么明显。
  • 顺便感谢格式化部分。下次我会努力做得更好;-)

标签: python arrays


【解决方案1】:

不知道为什么人们不赞成这个问题,因为这是非常有效的。

现在,考虑一下:

>>> mylist1 = [(1,2), (3,4)]
>>> mylist2 = list(mylist1)

>>> mylist1
[(1, 2), (3, 4)]
>>> mylist2
[(1, 2), (3, 4)]

>>> mylist2[0] = (0, 0)

>>> mylist1
[(1, 2), (3, 4)]
>>> mylist2
[(0, 0), (3, 4)]

如您所见,list() 创建了列表的副本,但该副本不是“深层”副本,如果列表包含可变对象(列表、字典或对象),则该副本只会复制引用这些对象而不是它们上的内容。例如:

>>> mylist1 = [[1,2], [3,4]]
>>> mylist2 = list(mylist1)
>>> mylist2[0][0] = 0
>>> mylist2
[[0, 2], [3, 4]]
>>> mylist1
[[0, 2], [3, 4]]

这是因为对第一个元素列表的引用被复制到新列表中,而不是它的内容或列表的完整副本,它仍然是同一个列表。

如前所述,使用copy.deepcopy

https://docs.python.org/3/library/copy.html#copy.deepcopy

你可以在那里阅读:

浅拷贝和深拷贝之间的区别仅与复合对象(包含其他对象的对象,如列表或类实例)有关:

  • 浅拷贝构造一个新的复合对象,然后(在可能的范围内)向其中插入对原始对象的引用。
  • 深拷贝构造一个新的复合对象,然后递归地将原始对象的副本插入其中。

针对您的特殊情况的另一种选择是使用这样的列表推导:

>>> mylist1 = [[1,2], [3,4]]
>>> mylist2 = [list(elem) for elem in mylist1] # < This one
>>> mylist1
[[1, 2], [3, 4]]
>>> mylist2
[[1, 2], [3, 4]]
>>> mylist2[0][0] = 0
>>> mylist1
[[1, 2], [3, 4]]
>>> mylist2
[[0, 2], [3, 4]]

这也会复制元素列表。

【讨论】:

    猜你喜欢
    • 2016-07-17
    • 2018-10-28
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    相关资源
    最近更新 更多