我偶尔使用numpy
,并且我试图变得更聪明,我如何对操作进行矢量化。我正在阅读一些代码并尝试理解以下语义:
arr_1[:] = arr_2
在这种情况下,
我理解,在arr[:, 0]
中,我们正在选择数组的第一列,但我对arr_1[:] = arr_2
和arr_1 = arr_2
之间的差异感到困惑。
答案 0 :(得分:7)
您的问题涉及基本Python语法和numpy
具体细节的混合。在许多方面,它对于列表是相同的,但不完全相同。
arr[:, 0]
返回arr
的第一列(视图),arr[:,0]=10
将该列的值设置为10.
arr[:]
返回arr
(alist[:]
返回列表的副本)。 arr[:]=arr2
执行就地替换;将arr
的值更改为arr2
的值。 arr2
的值将根据需要进行广播和复制。
arr=arr2
设置arr
变量指向的对象。现在arr
和arr2
指向相同的事物(无论是数组,列表还是其他任何东西)。
arr[...]=arr2
也有效
在交互式会话中玩这些操作。尝试arr2
形状的变化,看看如何广播数值。同时检查id(arr)
以查看变量指向的对象。并arr.__array_interface__
查看数组的数据缓冲区。这有助于您将视图与副本区分开来。
答案 1 :(得分:6)
arr_1[:] = ...
更改arr_1
引用的现有列表对象的元素。
arr_1 = ...
使名称arr_1
引用不同的列表对象。
主要区别在于,如果某些其他名称也引用了原始列表对象,会发生什么。如果是这种情况,那么前者会更新两个名称所指的东西;而后者改变一个名称所指的是什么,而另一个名称指的是原始的东西。
>>> a = [0]
>>> b = a
>>> a[:] = [1]
>>> print(b)
[1] <--- note, change reflected by a and b
>>> a = [2]
>>> print(b)
[1] <--- but now a points at something else, so no change to b
答案 2 :(得分:2)
使用arr_1[:] = arr_2
是arr_1.__setitem__(slice(None, None), arr_2)
的快捷方式。使用arr_1 = arr_2
代替__setitem__
的原因是,您正在修改arr_1
,而当您说arr_1 = arr_2
时,您正在重新定义arr_1
。因此,使用__setitem__
会修改对arr_1
对象的其他引用,而不仅仅是重新定义arr_1
。
答案 3 :(得分:2)
也许最好通过使用id
来检查每个变量的内存位置。
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
>>> id(arr1)
4595568512
>>> id(arr2)
4595566192
# Slice assignment
arr1[:] = arr2
>>> arr1
array([4, 5, 6])
>>> id(arr1) # The object still points to the same memory location of `arr1`.
4595568512
# Reassignment.
arr1 = arr2
>>> id(arr1) # The object is now pointing to the object located to where `arr2` points.
4595566192