Ответ 1
"Лучшим способом" для делегирования __iter__
будет:
def __iter__(self):
return iter(self._iterable)
В качестве альтернативы, возможно, стоит знать о:
def __iter__(self):
for item in self._iterable:
yield item
Это позволит вам играть с каждым элементом перед его возвратом (например, если вы хотите yield item * 2
).
И как @Lattyware упоминает в комментариях, PEP380 (намеченный для включения в Python 3.3) позволит:
def __iter__(self):
yield from self._iterable
Обратите внимание, что может возникнуть соблазн сделать что-то вроде:
def __init__(self, iterable):
self.__iter__ = iterable.__iter__
Но это не сработает: iter(foo)
напрямую вызывает метод __iter__
на type(foo)
, минуя foo.__iter__
. Рассмотрим, например:
class SurprisingIter(object):
def __init__(self):
self.__iter__ = lambda self: iter("abc")
def __iter__(self):
return iter([1, 2, 3])
Вы ожидаете, что list(SurprisingIter())
вернет ["a", "b", "c"]
, но на самом деле возвращает [1, 2, 3]
.