Python中的常规赋值只是在本地或全局变量字典中更改引用,而不是修改现有变量。这意味着简单地赋值给x将不会将值放入数组的元素中,而是将x从数组元素引用切换为对您分配的值的引用。要实际修改数组的元素,x应该用省略号索引。
该部分包含你的代码示例。
所以用我的话说,就地x[...]=...修改x; x=...会打破链接到nditer变量,而不是改变它。这就好像x[:]=...只适用于任何维度的数组(包括0d)。在这种情况下x,不仅仅是一个数字,它是一个数组。
也许最接近这个nditer迭代的是,没有nditer:In [667]: for i,x in np.ndenumerate(a):
...: print(i,x)
...: a[i] = 2*x
...:
(0, 0) 0
(0, 1) 1
...
(1, 2) 5
In [668]: a
Out[668]:
array([[ 0, 2, 4],
[ 6, 8, 10]])
请注意,我必须a[i]直接进行索引和修改。我不能使用,x = 2*x。在这个迭代中x是一个标量,因此不可变In [669]: for i,x in np.ndenumerate(a):
...: x[...] = 2*x
...
TypeError: 'numpy.int32' object does not support item assignment
但在这种nditer情况下x是一个0D数组,并且是可变的。In [671]: for x in np.nditer(a, op_flags=['readwrite']):
...: print(x,type(x),x.shape)
...: x[...] = 2*x
...:
0 ()
4 ()
...
并且因为它是0d,x[:]所以不能用来代替x[...]----> 3 x[:] = 2*x
IndexError: too many indices for array
更简单的数组迭代也可以提供洞察力:In [675]: for x in a:
...: print(x,x.shape)
...: x[:] = 2*x
...:
[ 0 8 16] (3,)
[24 32 40] (3,)
这在迭代的行(第一个dim)上迭代a。 x然后一维阵列,并且可与被修改x[:]=...或x[...]=...。
如果我添加了external_loop从下一个标志部分,x现在是一维数组,并x[:]=会工作。但x[...]=仍然有效,更一般。 x[...]用于所有其他nditer示例。In [677]: for x in np.nditer(a, op_flags=['readwrite'],flags=['external_loop']):
...: print(x,type(x),x.shape)
...: x[...] = 2*x
[ 0 16 32 48 64 80] (6,)
比较这个简单的行迭代(在2d数组上):In [675]: for x in a:
...: print(x,x.shape)
...: x[:] = 2*x
...:
[ 0 8 16] (3,)
[24 32 40] (3,)
这在迭代的行(第一个dim)上迭代a。 x然后一维阵列,并且可与被修改x[:]=...或x[...]=...。