Python Language
Iterables e Iterators
Ricerca…
Iterator vs Iterable vs Generator
Un iterabile è un oggetto che può restituire un iteratore . Qualsiasi oggetto con stato che ha un metodo __iter__
e restituisce un iteratore è un iterabile. Potrebbe anche essere un oggetto senza stato che implementa un metodo __getitem__
. - Il metodo può prendere indici (partendo da zero) e generare un IndexError
quando gli indici non sono più validi.
La classe str
di Python è un esempio di iterable __getitem__
.
Un Iterator è un oggetto che produce il valore successivo in una sequenza quando si chiama next(*object*)
su qualche oggetto. Inoltre, qualsiasi oggetto con un metodo __next__
è un iteratore. Un iteratore solleva StopIteration
dopo aver esaurito l'iteratore e non può essere riutilizzato a questo punto.
Classi Iterable:
Le classi Iterable definiscono un __iter__
e __next__
. Esempio di una classe iterabile:
class MyIterable:
def __iter__(self):
return self
def __next__(self):
#code
#Classic iterable object in older versions of python, __getitem__ is still supported...
class MySequence:
def __getitem__(self, index):
if (condition):
raise IndexError
return (item)
#Can produce a plain `iterator` instance by using iter(MySequence())
Cercando di creare un'istanza della classe astratta dal modulo delle collections
per vederlo meglio.
Esempio:
import collections
>>> collections.Iterator()
>>> TypeError: Cant instantiate abstract class Iterator with abstract methods next
>>> TypeError: Cant instantiate abstract class Iterator with abstract methods __next__
Gestisci la compatibilità con Python 3 per le classi iterabili in Python 2 effettuando le seguenti operazioni:
class MyIterable(object): #or collections.Iterator, which I'd recommend....
....
def __iter__(self):
return self
def next(self): #code
__next__ = next
Entrambi sono ora iteratori e possono essere collegati in loop:
ex1 = MyIterableClass()
ex2 = MySequence()
for (item) in (ex1): #code
for (item) in (ex2): #code
I generatori sono semplici modi per creare iteratori. Un generatore è un iteratore e un iteratore è un iterabile.
Cosa può essere iterabile
Iterable può essere qualsiasi cosa per cui gli articoli vengono ricevuti uno per uno, solo in avanti . Le collezioni Python integrate sono iterabili:
[1, 2, 3] # list, iterate over items
(1, 2, 3) # tuple
{1, 2, 3} # set
{1: 2, 3: 4} # dict, iterate over keys
I generatori restituiscono iterabili:
def foo(): # foo isn't iterable yet...
yield 1
res = foo() # ...but res already is
Iterazione su intero iterabile
s = {1, 2, 3}
# get every element in s
for a in s:
print a # prints 1, then 2, then 3
# copy into list
l1 = list(s) # l1 = [1, 2, 3]
# use list comprehension
l2 = [a * 2 for a in s if a > 2] # l2 = [6]
Verifica solo un elemento in iterabile
Usa decompressione per estrarre il primo elemento e assicurarti che sia l'unico:
a, = iterable
def foo():
yield 1
a, = foo() # a = 1
nums = [1, 2, 3]
a, = nums # ValueError: too many values to unpack
Estrarre i valori uno per uno
Inizia con iter()
integrato per ottenere iteratore su iterabile e usa next()
per ottenere gli elementi uno alla volta fino a quando StopIteration
viene StopIteration
significare la fine:
s = {1, 2} # or list or generator or even iterator
i = iter(s) # get iterator
a = next(i) # a = 1
b = next(i) # b = 2
c = next(i) # raises StopIteration
Iterator non è rientranti!
def gen():
yield 1
iterable = gen()
for a in iterable:
print a
# What was the first item of iterable? No way to get it now.
# Only to get a new iterator
gen()