我是python的初学者,我不希望这些数组相互复制,但它们是自动的:
a = numpy.zeros(4)
b = a
a[1] = 10
print b[1]
并返回10而不是0.如何断开这两个数组?
答案 0 :(得分:4)
“数组自动相互复制”是一个错误的陈述,原因有几个。主要原因是您只有一个数组,以及两个引用该数组的变量名称。
以下是三种复制numpy数组的方法(即创建与它完全相同的另一个数组):
>>> a = numpy.zeros(4)
>>> b = a.copy()
>>> c = numpy.copy(a)
>>> d = numpy.array(a)
>>> a[1] = 10
>>> a
array([ 0., 10., 0., 0.])
>>> b
array([ 0., 0., 0., 0.])
>>> c
array([ 0., 0., 0., 0.])
>>> d
array([ 0., 0., 0., 0.])
请注意,切片复制(例如e = a[:])
将不与numpy数组配合使用。
答案 1 :(得分:2)
您需要一份副本:
b = a.copy()
b = a
创建一个引用a is b
,它们都指向内存中的相同位置,a.copy()
实际上创建了一个新对象。
In [5]: a = numpy.zeros(4)
In [6]: b = a # reference
In [7]: id(a)
Out[7]: 140335847505968
In [8]: id(b) # same id's
Out[8]: 140335847505968
In [9]: a is b
Out[9]: True
In [10]: b = a.copy() # new object
In [11]: id(a)
Out[11]: 140335847505968
In [12]: id(b) # # now different id's
Out[12]: 140335437696176
In [13]: a is b # b is no longer pointing to the same memory location
Out[13]: False
如果使用basic slicing对数组进行切片,则id会有所不同,但任何更改都会反映在a和b中,就像使用基本索引时一样基本切片生成的所有数组总是原始数组的视图。 A view是一个不拥有数据的数组,而是引用另一个数组的数据。所以视图是一个新对象,但是内容仍然属于原始数组。
但是,使用advanced indexing 高级索引始终会返回数据的副本
In [141]: a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [142]: b = a[1:7:2] # basic indexing/view
In [143]: id(a)
Out[143]: 140335437385856
In [144]: id(b)
Out[144]: 140335437356528
In [145]: b[0] = 999
In [146]: a
Out[146]: array([ 0, 999, 2, 3, 4, 5, 6, 7, 8, 9])
In [148]: b
Out[148]: array([999, 3, 5])
In [149]: a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [150]: b = a[[0,3,5]] # advanced indexing/copy
In [151]: b
Out[151]: array([0, 3, 5])
In [152]: b[0] = 999
In [153]: a
Out[153]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [154]: b
Out[154]: array([999, 3, 5])
In [157]: a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [158]: b = a[a] # copy
In [159]: b
Out[159]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [160]: b[0] = 99
In [161]: a
Out[161]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [162]: b
Out[162]: array([99, 1, 2, 3, 4, 5, 6, 7, 8, 9])
这是特定的numpy行为,切割常规python平面列表将始终创建一个新列表,其中a中的更改不会反映在b中。
In [190]: a = [1,2,3,4,5]
In [191]: b = a[:3]
In [192]: b[0] = 999
In [193]: a
Out[193]: [1, 2, 3, 4, 5]
In [194]: b
Out[194]: [999, 2, 3]
如果列表包含子列表并且您创建了一个浅表副本,那么您将会遇到python列表:
In [197]: a = [[1,2,3],[4,5]]
In [198]: b = a[:]
In [199]: id(a)
Out[199]: 140335437468296
In [200]: id(b)
Out[200]: 140335437417992
In [201]: b[0][0] = 999
In [202]: b
Out[202]: [[999, 2, 3], [4, 5]]
In [203]: a
Out[203]: [[999, 2, 3], [4, 5]]
您需要制作copy.deepcopy:
In [204]: a = [[1,2,3],[4,5]]
In [205]: from copy import deepcopy
In [206]: b = deepcopy(a)
In [207]: b[0][0] = 999
In [208]: b
Out[208]: [[999, 2, 3], [4, 5]]
In [209]: a
Out[209]: [[1, 2, 3], [4, 5]]
答案 2 :(得分:-1)
记住Python中的列表是可变的,这意味着当您执行分配操作时,它不会创建它的副本,而是复制引用。这意味着两个变量都是相同的列表。
你可以这样做:
b = a[::]
,它会创建原始列表的副本。
无论如何,我建议您阅读Python.org列表部分以获取更多信息。
答案 3 :(得分:-1)
您可以像这样使用复制模块
from copy import copy
a = numpy.zeros(4)
b = copy(a)
a[1] = 10
print b[1]
这与您b = a
执行a
时将b
的引用分配给{{1}}这一事实有关。
有关详细信息,请参阅此答案:How to clone or copy a list?