Domanda

Nonostante abbia letto, non riesco ancora a capire come funziona __iter__ . Quale sarebbe una semplice spiegazione?

Ho visto def__iter __ (self): return self . Non vedo come funziona o i passaggi su come funziona.

È stato utile?

Soluzione

Un iteratore deve definire due metodi: __iter __ () e __next __ () ( next () in python2). Di solito, l'oggetto stesso definisce il metodo __next __ () o next () , quindi si restituisce semplicemente come iteratore. Questo crea un iterabile che è anche esso stesso un iteratore . Questi metodi sono utilizzati da per e nelle istruzioni .

Altri suggerimenti

Per quanto posso dirlo:

__iter__ definisce un metodo su una classe che restituirà un iteratore (un oggetto che produce successivamente l'elemento successivo contenuto dal tuo oggetto).

L'oggetto iteratore che restituisce __iter __ () può essere praticamente qualsiasi oggetto, purché definisca un metodo next () .

Il metodo next verrà chiamato da istruzioni come per ... in ... per produrre l'elemento successivo e next () dovrebbe sollevare l'eccezione StopIteration quando non ci sono più elementi.

La cosa fantastica di questo è che consente a tu di definire come viene ripetuto il tuo oggetto e __iter__ fornisce un'interfaccia comune con cui ogni altra funzione python sa come lavorare.

Le specifiche per def __iter __ (self): sono: restituisce un iteratore. Quindi, se self è un iteratore, return self è chiaramente appropriato.

" Essere un iteratore " significa "avere un metodo __next __ (self) " (in Python 3; in Python 2, il nome del metodo in questione è purtroppo semplicemente next invece, chiaramente un glitch nella progettazione di un nome per un metodo speciale).

In Python 2.6 e versioni successive, il modo migliore per implementare un iteratore è generalmente quello di utilizzare la classe base astratta appropriata dalla libreria standard collections module - in Python 2.6, il codice potrebbe essere (ricordati di chiamare il metodo __next__ invece in Python 3):

import collections

class infinite23s(collections.Iterator):
  def next(self): return 23

un'istanza di questa classe restituirà un numero infinito di copie di 23 quando viene ripetuto (come itertools.repeat (23) ), quindi il ciclo deve essere terminato altrimenti. Il punto è che la sottoclasse di collections.Iterator aggiunge il giusto metodo __iter__ per tuo conto - non un grosso problema qui, ma un buon principio generale (evita il codice ripetitivo, boilerplate come __iter__ standard di una riga degli iteratori - in ripetizione, non c'è valore aggiunto e molto valore sottratto! -).

Una classe che supporta il metodo __iter__ restituirà un'istanza di oggetto iteratore: un oggetto che supporta il metodo next () . Questo oggetto sarà utilizzabile nelle istruzioni "per" e " in " ;.

In Python, un iteratore è qualsiasi oggetto che supporti il ??protocollo iteratore. Parte di quel protocollo è che l'oggetto deve avere un metodo __iter __ () che restituisce l'oggetto iteratore. Suppongo che questo ti dia una certa flessibilità in modo che un oggetto possa passare le responsabilità dell'iteratore a una classe interna o creare un oggetto speciale. In ogni caso, il metodo __iter __ () di solito ha solo una riga e quella linea è spesso semplicemente return self

L'altra parte del protocollo è il metodo next () , ed è qui che si svolge il vero lavoro. Questo metodo deve capire o creare o ottenere la cosa successiva e restituirla. Potrebbe essere necessario tenere traccia di dove si trova in modo che la prossima volta che viene chiamato, restituisca davvero la cosa successiva.

Una volta che hai un oggetto che restituisce la cosa successiva in una sequenza, puoi comprimere un ciclo for che assomiglia a questo:

myname = "Fredericus"
x = []
for i in [1,2,3,4,5,6,7,8,9,10]:
   x.append(myname[i-1])
   i = i + 1 # get the next i
print x

in questo:

myname = "Fredericus"
x = [myname[i] for i in range(10)]
print x

Si noti che non esiste alcun luogo in cui abbiamo codice che ottiene il valore successivo di i poiché range (10) è un oggetto che SEGUE il protocollo iteratore e la comprensione dell'elenco è un costrutto che UTILIZZA il protocollo iteratore.

Puoi anche USARE direttamente il protocollo iteratore. Ad esempio, quando scrivo script per elaborare file CSV, scrivo spesso questo:

mydata = csv.reader(open('stuff.csv')
mydata.next()
for row in mydata:
    # do something with the row.

Sto usando l'iteratore direttamente chiamando next () per saltare la riga di intestazione, quindi utilizzandolo indirettamente tramite l'operatore in incorporato in per istruzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top