以下代码演示了使用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
,因为a
和b
都被定义为数据切片,因此不再需要链接。
这种行为是有意的吗?如果是这样,它背后的逻辑是什么?
答案 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对象的行为方式相同。