Що означає 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.