“三点"是什么意思?在 Python 中,当索引什么看起来像一个数字时意味着什么?

2022-01-10 00:00:00 python numpy iterator

问题描述

下面的x[...]是什么意思?

a = np.arange(6).reshape(2,3)
for x in np.nditer(a, op_flags=['readwrite']):
    x[...] = 2 * x


解决方案

虽然建议重复Python Ellipsis 对象做什么? 在一般 python 上下文中回答了这个问题,我认为它在 nditer 循环中的使用需要添加信息.

While the proposed duplicate What does the Python Ellipsis object do? answers the question in a general python context, its use in an nditer loop requires, I think, added information.

https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values

Python 中的正则赋值只是更改本地或全局变量字典中的引用,而不是修改现有变量.这意味着简单地分配给 x 不会将值放入数组的元素中,而是将 x 从数组元素引用切换为对您分配的值的引用.要实际修改数组的元素,x 应使用省略号进行索引.

Regular assignment in Python simply changes a reference in the local or global variable dictionary instead of modifying an existing variable in place. This means that simply assigning to x will not place the value into the element of the array, but rather switch x from being an array element reference to being a reference to the value you assigned. To actually modify the element of the array, x should be indexed with the ellipsis.

该部分包含您的代码示例.

That section includes your code example.

所以用我的话来说,x[...] = ... 就地修改了xx = ... 会破坏到 nditer 变量的链接,而不是更改它.它类似于 x[:] = ... 但适用于任何维度的数组(包括 0d).在这种情况下,x 不仅仅是一个数字,它还是一个数组.

So in my words, the x[...] = ... modifies x in-place; x = ... would have broken the link to the nditer variable, and not changed it. It's like x[:] = ... but works with arrays of any dimension (including 0d). In this context x isn't just a number, it's an array.

也许最接近这个 nditer 迭代的东西,没有 nditer 是:

Perhaps the closest thing to this nditer iteration, without nditer is:

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 是一个标量,因此不可变

Notice that I had to index and modify a[i] directly. I could not have used, x = 2*x. In this iteration x is a scalar, and thus not mutable

In [669]: for i,x in np.ndenumerate(a):
     ...:     x[...] = 2 * x
  ...
TypeError: 'numpy.int32' object does not support item assignment

但在 nditer 的情况下,x 是一个 0d 数组,并且是可变的.

But in the nditer case x is a 0d array, and mutable.

In [671]: for x in np.nditer(a, op_flags=['readwrite']):
     ...:     print(x, type(x), x.shape)
     ...:     x[...] = 2 * x
     ...:     
0 <class 'numpy.ndarray'> ()
4 <class 'numpy.ndarray'> ()
...

而且因为是0d,所以不能用x[:]代替x[...]

And because it is 0d, x[:] cannot be used instead of x[...]

----> 3     x[:] = 2 * x
IndexError: too many indices for array

更简单的数组迭代也可能提供洞察力:

A simpler array iteration might also give insight:

In [675]: for x in a:
     ...:     print(x, x.shape)
     ...:     x[:] = 2 * x
     ...:     
[ 0  8 16] (3,)
[24 32 40] (3,)

这会在 a 的行(第一个暗淡)上进行迭代.x 是一维数组,可以使用 x[:]=...x[...]=....

this iterates on the rows (1st dim) of a. x is then a 1d array, and can be modified with either x[:]=... or x[...]=....

如果我从下一个 external_loop 标志-external-loop" rel="noreferrer">section,x 现在是一维数组,x[:] = 可以工作.但是 x[...] = 仍然有效并且更通用.x[...] 用于所有其他 nditer 示例.

And if I add the external_loop flag from the next section, x is now a 1d array, and x[:] = would work. But x[...] = still works and is more general. x[...] is used all the other nditer examples.

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] <class 'numpy.ndarray'> (6,)

比较这个简单的行迭代(在二维数组上):

Compare this simple row iteration (on a 2d array):

In [675]: for x in a:
     ...:     print(x, x.shape)
     ...:     x[:] = 2 * x
     ...:     
[ 0  8 16] (3,)
[24 32 40] (3,)

这会在 a 的行(第一个暗淡)上进行迭代.x 是一维数组,可以使用 x[:] = ...x[...] = ....

this iterates on the rows (1st dim) of a. x is then a 1d array, and can be modified with either x[:] = ... or x[...] = ....

阅读并试验这个 nditer 页面,一直到最后.nditer 本身在 python 中并没有那么有用.它不会加速迭代 - 直到您将代码移植到 cython.np.ndindex 是为数不多的非编译 numpy 函数之一使用 nditer.

Read and experiment with this nditer page all the way through to the end. By itself, nditer is not that useful in python. It does not speed up iteration - not until you port your code to cython.np.ndindex is one of the few non-compiled numpy functions that uses nditer.

相关文章