Что означает 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,)
Сравните эту простую итерацию строки (на 2d массиве):
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
свой код на cython
. np.ndindex
- одна из немногих не скомпилированных функций numpy
которая использует nditer
.
Должен быть интересный способ понять это. https://www.youtube.com/watch?v=65_-6kEAq58