Що означає 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 = ...
порушив би посилання на 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
. np.ndindex
є однією з небагатьох некомпільованих numpy
функцій, яка використовує nditer
.