La risposta, completa e corretta.
for
, sia per loop che per list comprehensions, chiamate iter()
su X
. iter()
restituirà un iterable se X
ha un metodo __iter__
o un metodo __getitem__
. Se implementa entrambi, viene utilizzato __iter__
. Se non hai né tu ottieni TypeError: 'Nothing' object is not iterable
.
Questo implementa una __getitem__
:
class GetItem(object):
def __init__(self, data):
self.data = data
def __getitem__(self, x):
return self.data[x]
utilizzati:
>>> data = range(10)
>>> print [x*x for x in GetItem(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Questo è un esempio di attuazione __iter__
:
class TheIterator(object):
def __init__(self, data):
self.data = data
self.index = -1
# Note: In Python 3 this is called __next__
def next(self):
self.index += 1
try:
return self.data[self.index]
except IndexError:
raise StopIteration
def __iter__(self):
return self
class Iter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
return TheIterator(data)
utilizzati:
>>> data = range(10)
>>> print [x*x for x in Iter(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Come si vede, è necessario entrambi implementare un iteratore e __iter__
che restituisce l'iteratore.
Si possono combinare:
class CombinedIter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
self.index = -1
return self
def next(self):
self.index += 1
try:
return self.data[self.index]
except IndexError:
raise StopIteration
Usage:
>>> well, you get it, it's all the same...
Ma allora si può avere un solo iteratore di andare in una sola volta. OK, in questo caso si può solo fare questo:
class CheatIter(object):
def __init__(self, data):
self.data = data
def __iter__(self):
return iter(self.data)
ma questo è barare, perché si sta solo riutilizzando il metodo di list
__iter__
. Un modo più semplice è quello di utilizzare la resa, e fare __iter__
in un generatore:
class Generator(object):
def __init__(self, data):
self.data = data
def __iter__(self):
for x in self.data:
yield x
Quest'ultimo è il modo in cui mi sento di raccomandare. Facile ed efficiente
Si noti che la parola chiave "in" viene utilizzata in due contesti distinti in Python. Esistono iterazioni (con la tastiera "for") e contesti booleani/condizionali (a volte con "if" o "while"). Quest'ultimo chiama i metodi __taintain__ per i suoi oggetti. –