为什么在numpy数组上使用* =修改原始数组?

时间:2018-02-19 17:32:09

标签: python numpy

以下代码演示了使用a*=3修改原始数据集,而a=a*3则不会:

data=np.array([[1,0],[3,4]])
a=data[0]
b=data[1]
a*=3
b=b*3
print(data)

给出:

[[3 0] [3 4]]

a*=3语句修改了矩阵数据,但b=b*3语句没有。 我希望2个分配都不会修改data,因为ab都被定义为数据切片,因此不再需要链接。 这种行为是有意的吗?如果是这样,它背后的逻辑是什么?

2 个答案:

答案 0 :(得分:3)

查看b>>> a.flags C_CONTIGUOUS : True F_CONTIGUOUS : True OWNDATA : False # <--- a does not copy data (a*=3 mutates original data) WRITEABLE : True ALIGNED : True WRITEBACKIFCOPY : False UPDATEIFCOPY : False >>> b.flags C_CONTIGUOUS : True F_CONTIGUOUS : True OWNDATA : True # <--- b is copied (the multiplication b*3 creates the copy) WRITEABLE : True ALIGNED : True WRITEBACKIFCOPY : False UPDATEIFCOPY : False 上的标记,特别是OWNDATA标记

data[0]

对象data不是切片,它是数组中可写的视图。  修改内容将修改a = data[0].copy()

  

这种行为是否有意?如果是这样,它背后的逻辑是什么?

是的,这是设计的。除非必要,否则它旨在防止复制。如果您需要numpy中的副本,请使用List<A> listA = new ArrayList<A>(); List<B> listB = new ArrayList<B>(); Set<Integer> aIdsFromBList = listB.stream().map(B::getAId).collect(Collectors.toSet()); return listA.stream .filter(a -> aIdsFromBList.contains(a.getId())) .collect(Collectors.toList()); 明确请求它。

答案 1 :(得分:1)

我认为这不是numpy特有的,但对于任何可变对象都是如此。例如,请参阅以下修改列表的代码(原型可变对象):

a = [1]
b = a
b += [2]
print(a, b) #prints [1, 2] [1, 2]
print(id(a), id(b)) #The same id

a = [1]
b = a
b = b + [2]
print(a, b) #prints [1], [1, 2]
print(id(a), id(b)) #Not the same id

因此,赋值将创建副本,而运算符(+ =)将修改对象。 numpy对象的行为方式相同。