复制列表嵌套列表的值而非引用

21
为了理解我在一个程序中试图找到行列式的“次要部分”时为什么会出现错误,我编写了一个更简单的程序,因为我的变量被搞乱了。下面的函数以2 * 2矩阵作为输入,并返回包含其行的列表(这是无意义和低效的,但我正在尝试理解其背后的理论)。
def alpha(A):   #where A will be a 2 * 2 matrix
    B = A       #the only purpose of B is to store the initial value of A, to retrieve it later
    mylist = []
    for i in range(2):
        for j in range(2):
            del A[i][j]
        array.append(A)
        A = B
    return mylist

然而,在这里B似乎是以动态的方式被赋予A的值,也就是说,我无法将A的初始值存储在B中以便稍后使用。为什么会这样呢?


2
array.append(A) 应该真的改为 mylist.append(A) 吗?如果不是,那么 array 是在哪里定义的? - CDspace
1
很抱歉,我担心您在复制array.append(A)时没有考虑到“array”是实际要追加的数组,即对应于该数组的变量,而不是一个“array”包。如果我漏掉了什么,请原谅。 - yohann.martineau
Python传递引用方式 - Daniel
为了漂亮的可视化,请比较[一]与[二]。 - Chris_Rands
3个回答

38

因为python通过引用传递列表

这意味着当你写下"b=a"的时候,你是在说a和b是同一个对象,当你改变b的时候,同时也会改变a,反之亦然

通过值来复制一个列表的方法:

new_list = old_list[:]

如果列表包含对象并且您也想复制它们,请使用通用的 copy.deepcopy():

import copy
new_list = copy.deepcopy(old_list)

6
在这种情况下,您需要创建一个deepcopy,因为它们有一个列表的列表。 - Moses Koledoye
1
哦,天啊,我花了好几个小时才弄明白为什么在JavaScript中完美运行的使用列表的递归算法在Python中却给我带来了各种疯狂的结果......copy.deepcopy万能。 - iamnicoj
警告:请阅读莫西斯上面的评论! - Brett Young

4

由于Python是按引用传递列表,因此AB是相同的对象。当你修改B时,你也在修改A。这种行为可以在一个简单的例子中演示:

>>> A = [1, 2, 3]
>>> def change(l):
...     b = l
...     b.append(4)
... 
>>> A
[1, 2, 3]
>>> change(A)
>>> A
[1, 2, 3, 4]
>>> 

如果您需要一个副本 A,请使用切片符号:

B = A [:]


0

A 看起来像是一个引用类型,而不是值类型。与例如 R 不同,引用类型在赋值时不会被复制。您可以使用 copy.copy 来深度复制一个元素。


copy.copy 做的是浅拷贝... copy.deepcopy 像其他人所说的那样做深拷贝。 - g19fanatic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接