2014-01-09 55 views
0

Hello Python/iPython用户。a = b似乎是相同的,而不是副本。为什么?

我发现了Python使用numpy数组的奇怪行为。我自己找到了解决问题的办法,但我很想得到解释。提前致谢。

这里的问题: 使用IPython中创建一个numpy的阵列和一个副本,称为B:

import numpy as np 
a=np.zeros(5) 
b=a 

然而,B似乎是相当的身份,而不是一个副本,因为改变b也会改变。

b[0]=1 
a 
array([ 1., 0., 0., 0., 0.]) 

的解决方案是使用b=a.copy()而非b=a,但我想明白为什么这是蟒蛇的情况。我对Matlab,R和Fortran非常熟悉,从未遇到过这样的问题。为什么有人想为同一个数据取一个名字而不是这个向量的副本?只是一些python特定的语法的东西,还是有更多的理解?

+0

如果你想真正了解这里发生了什么,读(http://nedbatchelder.com/text/names.html)由斯内德尔德[关于Python的名称和值事实与神话。 –

回答

4

它只是一个python约定。所有的赋值都不会做任何事情,只是为现有的对象创建一个新的句柄。这是一个非常明智的规则,因为它使语义简单而透明。在其他语言中,您可能经常会想知道您是修改现有对象还是创建一个新句柄。如果你想要做的不是在现有对象上打一个新名字,python总是强迫你做出明确的表示。至于你为什么要这样做:试着找到任何一段python代码,看看它包含了多少赋值语句。显然有它的用途;)。

-1

这确实是python中一些对象的特殊性。 numpy数组实际上是从python的“list”对象派生出来的,它的作用方式与此相同。

实际上,当您在python(或一个numpy数组)中创建一个列表时,数据存储在内存中的给定位置。 的标识号被关联到该位置,并且可以使用该函数“ID”

a = [1, 2, 3] 
print id(a) 

如果键入“B = A”看到它,B将朝向相同的存储单元的一个点。因此a和b将具有相同的 识别号码。

a = [1, 2, 3] 
print id(a) 
b = a 
print id(b) 

你必须非常小心,因为任何对will的修改都会影响b。 “复制”方法将创建的一个深拷贝,这意味着30b存储到一个新的存储位置

a = numpy.array([1, 2, 3]) 
print id(a) 
b = a 
print id(b) 
c = a.copy() 
print id(c) 

有相当于现在的“复制”的名单,而不是必须使用“:”符号

a = [1, 2, 3] 
print id(a) 
b = a 
print id(b) #a and b are the same 
c = a[:] 
print id(c) #c is a deep copy of a 
+0

你最后的评论'c是一个深的副本'是错误的:c只是一个浅拷贝(所以任何子列表都是原件而不是副本)。如果你想要一个深拷贝,使用'from copy import deepcopy'然后'c = deepcopy(a)'。有多种复制列表的方法:'c = list(a)'产生一个浅表副本,它总是一个列表,但是可以处理任何包括发生器的序列,'c = a [:]'产生一个浅拷贝,与原始类型相同(例如,可以是'tuple'或'str'),但仅适用于可分片序列,并支持函数copy.copy和copy.deepcopy。 – Duncan

+0

另外,numpy数组并不是从Python列表派生的。 'ndarray.copy()'也不会创建深层副本。 –

相关问题