In [48]: arr = np.arange(20)
...: with np.nditer(arr[np.nonzero(arr)],
...: op_flags=['readwrite']) as it:
...: for x in it:
...: x[...] = 5
...: arr
Out[48]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
Это не меняет arr
, потому что оно не повторяется на arr
. Вместо этого он делает:
In [49]: arr = np.arange(20)
...: arr1 = arr[np.nonzero(arr)]
...: with np.nditer(arr1,
...: op_flags=['readwrite']) as it:
...: for x in it:
...: x[...] = 5
...: arr1
Out[49]: array([5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])
In [50]: _.shape
Out[50]: (19,)
arr1
не view
из arr
, это выборка, новый массив без общего буфера данных.
Если вы хотитечтобы изменить arr
, вы должны выполнить итерацию, а не копию. Проведите тест или что-нибудь необычное внутри цикла.
In [51]: arr = np.arange(20)
...: with np.nditer(arr,
...: op_flags=['readwrite']) as it:
...: for x in it:
...: if x > 0:
...: x[...] = 5
...: arr
Out[51]: array([0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])
Но почему вы используете nditer
? Вы уже знаете, как выполнить выборочное присваивание такого рода, используя неитерационные методы:
array[np.nonzero(array)] = 5
. В этом случае присваивание =
следует сразу за расширенным индексированием, а Python использует array.__setitem__
вместоarr.__getitem__
.
Итерируя по срезу, view
меняет источник:
In [52]: arr = np.arange(20)
...: with np.nditer(arr[5:],
...: op_flags=['readwrite']) as it:
...: for x in it:
...: x[...] = 5
...: arr
Out[52]: array([0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])