Podczas gdy proponowany duplikat Co robi obiekt Python Ellipsis? odpowiada na pytanie w ogólnym pythonkontekście, jego użycie w nditerpętli wymaga, jak sądzę, dodatkowych informacji.
Zwykłe przypisanie w Pythonie po prostu zmienia odniesienie w lokalnym lub globalnym słowniku zmiennych zamiast modyfikować istniejącą zmienną w miejscu. Oznacza to, że zwykłe przypisanie do x nie spowoduje umieszczenia wartości w elemencie tablicy, ale raczej przełączy x z odniesienia do elementu tablicy na odniesienie do przypisanej wartości. Aby faktycznie zmodyfikować element tablicy, x powinno być indeksowane za pomocą wielokropka.
Ta sekcja zawiera przykładowy kod.
Więc, moim zdaniem, x[...] = ...modyfikacje xw miejscu; x = ...złamałby link do nditerzmiennej i nie zmieniłby jej. To tak, x[:] = ...ale działa z tablicami o dowolnym wymiarze (w tym 0d). W tym kontekście xto nie tylko liczba, to tablica.
Być może najbliższą rzeczą do tej nditeriteracji, bez której nditerjest:
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]])
Zauważ, że musiałem a[i]bezpośrednio indeksować i modyfikować . Nie mogłem użyć x = 2*x,. W tej iteracji xjest skalarem, a zatem nie podlega zmianom
In [669]: for i,x in np.ndenumerate(a):
...: x[...] = 2 * x
...
TypeError: 'numpy.int32' object does not support item assignment
Ale w tym nditerprzypadku xjest to tablica 0d i mutowalna.
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'> ()
...
A ponieważ jest 0d, x[:]nie można go użyć zamiastx[...]
----> 3 x[:] = 2 * x
IndexError: too many indices for array
Prostsza iteracja tablicy może również dać wgląd:
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0816] (3,)
[243240] (3,)
to iteruje w rzędach (1 wymiar) a. xjest wtedy tablicą 1d i można ją modyfikować za pomocą x[:]=...lub x[...]=....
A jeśli dodam external_loopflagę z następnej sekcji , xjest teraz tablicą 1d i x[:] =zadziała. Ale x[...] =nadal działa i jest bardziej ogólny. x[...]używane są wszystkie inne nditerprzykłady.
In [677]: for x in np.nditer(a, op_flags=['readwrite'], flags=['external_loop']):
...: print(x, type(x), x.shape)
...: x[...] = 2 * x
[ 01632486480] <class 'numpy.ndarray'> (6,)
Porównaj tę prostą iterację wiersza (na tablicy 2d):
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0816] (3,)
[243240] (3,)
to iteruje w rzędach (1 wymiar) a. xjest wtedy tablicą 1d i można ją modyfikować za pomocą x[:] = ...lub x[...] = ....
Przeczytaj i eksperymentuj z tą nditerstroną do końca. Sam w sobie nditernie jest tak przydatny w python. Nie przyspiesza iteracji - dopóki nie przeniesiesz kodu do cython. np.ndindexjest jedną z niewielu niekompilowanych numpyfunkcji, które używają nditer.
Odpowiedzi:
Podczas gdy proponowany duplikat Co robi obiekt Python Ellipsis? odpowiada na pytanie w ogólnym
python
kontekście, jego użycie wnditer
pętli wymaga, jak sądzę, dodatkowych informacji.https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values
Ta sekcja zawiera przykładowy kod.
Więc, moim zdaniem,
x[...] = ...
modyfikacjex
w miejscu;x = ...
złamałby link donditer
zmiennej i nie zmieniłby jej. To tak,x[:] = ...
ale działa z tablicami o dowolnym wymiarze (w tym 0d). W tym kontekściex
to nie tylko liczba, to tablica.Być może najbliższą rzeczą do tej
nditer
iteracji, bez którejnditer
jest: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]])
Zauważ, że musiałem
a[i]
bezpośrednio indeksować i modyfikować . Nie mogłem użyćx = 2*x
,. W tej iteracjix
jest skalarem, a zatem nie podlega zmianomIn [669]: for i,x in np.ndenumerate(a): ...: x[...] = 2 * x ... TypeError: 'numpy.int32' object does not support item assignment
Ale w tym
nditer
przypadkux
jest to tablica 0d i mutowalna.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'> () ...
A ponieważ jest 0d,
x[:]
nie można go użyć zamiastx[...]
----> 3 x[:] = 2 * x IndexError: too many indices for array
Prostsza iteracja tablicy może również dać wgląd:
In [675]: for x in a: ...: print(x, x.shape) ...: x[:] = 2 * x ...: [ 0 8 16] (3,) [24 32 40] (3,)
to iteruje w rzędach (1 wymiar)
a
.x
jest wtedy tablicą 1d i można ją modyfikować za pomocąx[:]=...
lubx[...]=...
.A jeśli dodam
external_loop
flagę z następnej sekcji ,x
jest teraz tablicą 1d ix[:] =
zadziała. Alex[...] =
nadal działa i jest bardziej ogólny.x[...]
używane są wszystkie innenditer
przykłady.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,)
Porównaj tę prostą iterację wiersza (na tablicy 2d):
In [675]: for x in a: ...: print(x, x.shape) ...: x[:] = 2 * x ...: [ 0 8 16] (3,) [24 32 40] (3,)
to iteruje w rzędach (1 wymiar)
a
.x
jest wtedy tablicą 1d i można ją modyfikować za pomocąx[:] = ...
lubx[...] = ...
.Przeczytaj i eksperymentuj z tą
nditer
stroną do końca. Sam w sobienditer
nie jest tak przydatny wpython
. Nie przyspiesza iteracji - dopóki nie przeniesiesz kodu docython
.np.ndindex
jest jedną z niewielu niekompilowanychnumpy
funkcji, które używająnditer
.źródło