Python中的数组是按值还是按引用赋值的?

3
我想知道为什么删除原始数组会影响复制的数组:
arr = [1,2,3]
arr1 = arr
del arr[:]
print(arr1) #this prints []

但是当我修改原始数组的元素时,复制的数组不会受到影响:
arr = [1,2,3]
arr1 = arr
arr = [4,5,6]
print(arr1) #this prints [1,2,3]

如果有人能够解释这个问题,我将不胜感激,提前致谢。

2
除非您没有修改原始数组的元素,否则您重新分配了变量。 - miradulo
2
可能是如何通过引用传递变量?的重复问题。 - Noah Bogart
那是一个列表。但是,在Python中,每个变量本质上都是一个对象引用。 - juanpa.arrivillaga
4个回答

7
您没有修改原始数组的元素,而是重新分配了一个新列表给arr变量。如果您正确访问其元素,则对元素进行更改的直观想法将反映在arr1中,因为列表在Python中是可变的。例如,
arr = [1,2,3]
arr1 = arr
arr[1] = 4
print(arr1) #this prints [1,4,3]

3

有几种方法可以复制数组,但是:

arr1 = arr

它不是其中之一(在C语言中,它只是一个别名指针)。尝试使用以下之一

arr1 = arr[:]  # slice that includes all elements, i.e. a shallow copy
arr1 = copy.copy(arr)  # from the copy module, does a shallow copy
arr1 = copy.deepcopy(arr)  # you guessed it.. ;-)

在上述任何一种方式之后,您会发现对arr1arr的更改是相互独立的(当然,如果您使用浅拷贝,则列表中的项目是共享的)。


3

在Python中,对象被认为是按引用传递的。但实际上有一些不同。

arr = [1, 2, 3]

这个语句做了两件事情。首先,它在内存中创建了一个列表对象;其次,它将 "arr" 标签指向了这个对象。

arr1 = arr

这个语句创建了一个新标签“arr1”,并将其指向与arr指向的同一个列表对象。
现在,在您原来的代码中,您做了以下操作:
del arr[:]

这将删除列表对象的元素,现在任何指向它的标签都将指向一个空列表。在您的第二组代码中,您执行了以下操作:

arr = [4, 5, 6]

这将在内存中创建一个新的列表对象,并将“arr”标签指向它。现在你有两个列表对象在内存中,每个对象由两个不同的标签指向。我刚才在控制台上检查了一下,arr指向[4,5,6],arr1指向[1,2,3]。
这里有一篇很好的文章:http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/

-3

你没有完全复制列表,而是只重新分配了变量名。

为了进行深度复制列表,请执行以下操作:

arr1 = [x for x in arr]

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