Что означает x[...]
ниже?
a = np.arange(6).reshape(2,3)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x
Что означает x[...]
ниже?
a = np.arange(6).reshape(2,3)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x
Ответы:
Хотя предлагаемый дубликат Что делает объект Python Ellipsis? отвечает на вопрос в общем python
контексте, его использование в nditer
цикле требует, я думаю, дополнительной информации.
https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values
Регулярное присвоение в 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 <class 'numpy.ndarray'> ()
4 <class 'numpy.ndarray'> ()
...
И поскольку это 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,)
это итерация по строкам (1-й размер) a
. x
тогда является 1d-массивом и может быть изменен с помощью x[:]=...
или x[...]=...
.
И если я добавлю external_loop
флаг из следующего раздела , он x
станет 1d-массивом и 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] <class 'numpy.ndarray'> (6,)
Сравните эту простую итерацию строки (в двумерном массиве):
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0 8 16] (3,)
[24 32 40] (3,)
это итерация по строкам (1-й размер) a
. x
тогда является 1d-массивом и может быть изменен с помощью x[:] = ...
или x[...] = ...
.
Прочтите и поэкспериментируйте с этой nditer
страницей до конца. Сам по себе nditer
не так уж и полезен python
. Это не ускоряет итерацию - пока вы не перенесете свой код в cython
. np.ndindex
- одна из немногих нескомпилированных numpy
функций, использующих nditer
.