Le risposte di cui sopra sono fantastiche, ma come la maggior parte di ciò che ho visto, non sottolineare il abbastanza distinzione per le persone come me.
Inoltre, le persone tendono ad avere "troppo Pythonic" mettendo definizioni come "X è un oggetto che ha __foo__()
metodo". Tali definizioni sono corrette: si basano sulla filosofia della tipizzazione delle anatre, ma l'attenzione sui metodi tende a mettersi in mezzo quando si cerca di comprendere il concetto nella sua semplicità.
Quindi aggiungo la mia versione.
In linguaggio naturale,
- iterazione è il processo di prendere un elemento alla volta in una fila di elementi.
In Python,
iterable è un oggetto che è, beh, iterable, che in poche parole, significa che può essere usato in iterazione, ad esempio con un for
loop. Come? Utilizzando iteratore . Spiegherò di seguito.
... mentre iteratore è un oggetto che definisce come eseguire effettivamente l'iterazione, in particolare qual è l' elemento successivo . Ecco perché deve avere un
next()
metodo.
Gli stessi iteratori sono anch'essi iterabili, con la distinzione che il loro __iter__()
metodo restituisce lo stesso oggetto ( self
), indipendentemente dal fatto che i suoi elementi siano stati consumati o meno dalle chiamate precedenti next()
.
Quindi cosa pensa l'interprete Python quando vede for x in obj:
un'istruzione?
Guarda, a for
ciclo. Sembra un lavoro per un iteratore ... Prendiamone uno. ... C'è questo obj
ragazzo, quindi chiediamolo.
"Mr. obj
, hai il tuo iteratore?" (... chiama iter(obj)
, che chiama
obj.__iter__()
, che distribuisce felicemente un nuovo brillante iteratore_i
.)
OK, è stato facile ... Cominciamo a iterare allora. ( x = _i.next()
... x = _i.next()
...)
Poiché Mr. è obj
riuscito in questo test (avendo un certo metodo che restituisce un iteratore valido), lo premiamo con l'aggettivo: ora puoi chiamarlo "Mr. iterabileobj
".
Tuttavia, in casi semplici, normalmente non beneficiate di avere iteratore e iterabile separatamente. Quindi definisci un solo oggetto, che è anche il suo iteratore. (A Python non importa davvero che _i
distribuito da obj
non sia poi così brillante, ma solo ilobj
stesso.)
Questo è il motivo per cui nella maggior parte degli esempi che ho visto (e ciò che mi aveva confuso ancora e ancora), puoi vedere:
class IterableExample(object):
def __iter__(self):
return self
def next(self):
pass
invece di
class Iterator(object):
def next(self):
pass
class Iterable(object):
def __iter__(self):
return Iterator()
Ci sono casi, tuttavia, in cui è possibile trarre vantaggio dalla separazione dell'iteratore dall'iterabile, ad esempio quando si desidera avere una riga di elementi, ma più "cursori". Ad esempio, quando si desidera lavorare con elementi "correnti" e "imminenti", è possibile avere iteratori separati per entrambi. O più thread estratti da un enorme elenco: ognuno può avere il proprio iteratore per attraversare tutti gli elementi. Vedi @ Raymond's e @ glglgl's risposte di sopra.
Immagina cosa potresti fare:
class SmartIterableExample(object):
def create_iterator(self):
# An amazingly powerful yet simple way to create arbitrary
# iterator, utilizing object state (or not, if you are fan
# of functional), magic and nuclear waste--no kittens hurt.
pass # don't forget to add the next() method
def __iter__(self):
return self.create_iterator()
Appunti:
Lo ripeterò ancora: iteratore non è iterabile . Iteratore non può essere utilizzato come "sorgente" in for
loop. Ciò di cui il for
loop ha principalmente bisogno è __iter__()
(che restituisce qualcosa con next()
).
Naturalmente, for
non è l'unico ciclo di iterazione, quindi sopra vale anche per alcuni altri costrutti ( while
...).
Iteratore next()
può lanciare StopIteration per fermare l'iterazione. Non è necessario, tuttavia, può iterare per sempre o utilizzare altri mezzi.
Nel suddetto "processo di pensiero", _i
non esiste davvero. Ho inventato quel nome.
C'è una piccola modifica in Python 3.x: next()
ora è necessario chiamare il metodo (non il built-in) __next__()
. Sì, avrebbe dovuto essere così da sempre.
Puoi anche pensarlo in questo modo: iterable ha i dati, iterator estrae l'elemento successivo
Disclaimer: non sono uno sviluppatore di alcun interprete Python, quindi non so davvero cosa "interpreti". Le riflessioni sopra sono solo una dimostrazione di come comprendo l'argomento da altre spiegazioni, esperimenti ed esperienze di vita reale di un novizio di Python.
collections.abc.AsyncIterator
test__aiter__
e__anext__
metodi. Questa è una nuova aggiunta in 3.6.