Cosa significa "tre punti" in Python quando si indicizza quello che sembra un numero?


Risposte:


70

Mentre il duplicato proposto Cosa fa l'oggetto Python Ellipsis? risponde alla domanda in un pythoncontesto generale , il suo utilizzo in un nditerciclo richiede, credo, informazioni aggiuntive.

https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values

L'assegnazione regolare in Python cambia semplicemente un riferimento nel dizionario delle variabili locali o globali invece di modificare una variabile esistente sul posto. Ciò significa che la semplice assegnazione a x non inserirà il valore nell'elemento dell'array, ma piuttosto commuterà x dall'essere un riferimento all'elemento dell'array all'essere un riferimento al valore assegnato. Per modificare effettivamente l'elemento dell'array, x dovrebbe essere indicizzato con i puntini di sospensione.

Quella sezione include il tuo esempio di codice.

Quindi, nelle mie parole, le x[...] = ...modifiche xsul posto; x = ...avrebbe interrotto il collegamento alla nditervariabile e non lo avrebbe modificato. È come x[:] = ...ma funziona con array di qualsiasi dimensione (incluso 0d). In questo contesto xnon è solo un numero, è un array.

Forse la cosa più vicina a questa nditeriterazione, senza 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]])

Si noti che ho dovuto indicizzare e modificare a[i]direttamente. Non avrei potuto usare x = 2*x,. In questa iterazione xè uno scalare, e quindi non mutabile

In [669]: for i,x in np.ndenumerate(a):
     ...:     x[...] = 2 * x
  ...
TypeError: 'numpy.int32' object does not support item assignment

Ma nel nditercaso xè un array 0d e mutabile.

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'> ()
...

E poiché è 0d, x[:]non può essere utilizzato al posto dix[...]

----> 3     x[:] = 2 * x
IndexError: too many indices for array

Un'iterazione di array più semplice potrebbe anche fornire informazioni dettagliate:

In [675]: for x in a:
     ...:     print(x, x.shape)
     ...:     x[:] = 2 * x
     ...:     
[ 0  8 16] (3,)
[24 32 40] (3,)

questo itera sulle righe (1 ° dim) di a. xè quindi un array 1d e può essere modificato con x[:]=...o x[...]=....

E se aggiungo il external_loopflag dalla sezione successiva , xora è un array 1d e x[:] =funzionerebbe. Ma x[...] =funziona ancora ed è più generale. x[...]viene utilizzato tutti gli altri nditeresempi.

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,)

Confronta questa semplice iterazione di riga (su un array 2d):

In [675]: for x in a:
     ...:     print(x, x.shape)
     ...:     x[:] = 2 * x
     ...:     
[ 0  8 16] (3,)
[24 32 40] (3,)

questo itera sulle righe (1 ° dim) di a. xè quindi un array 1d e può essere modificato con x[:] = ...o x[...] = ....

Leggi e sperimenta questa nditerpagina fino alla fine. Di per sé, nditernon è così utile in python. Non accelera l'iterazione, non finché non si porta il codice a cython. np.ndindexè una delle poche numpyfunzioni non compilate che utilizza nditer.


Nota che cose come x [1,:, ...] sono anche una sintassi consentita. Lasciato per riferimento futuro.
borgr
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.