← Все вопросы
Как сделать свой класс итерируемым, чтобы по нему работал for ?
16
Хочу, чтобы можно было писать for item in my_collection:. Сейчас выдаёт TypeError: 'MyCollection' object is not iterable. Что нужно реализовать — __iter__, __next__, или можно через yield?
2 ответа
27
✓ Принятый ответ — помог автору
Самый простой и чистый способ — сделать __iter__ генератором через yield:
class MyCollection:
def __init__(self, items):
self.items = items
def __iter__(self):
for x in self.items:
yield x
Теперь for item in MyCollection([1, 2, 3]): работает. yield сам создаёт итератор, тебе не надо вручную писать __next__ и кидать StopIteration.
Классический способ «по учебнику» — два метода: __iter__ возвращает объект-итератор (часто self), а __next__ выдаёт следующий элемент и кидает StopIteration, когда всё кончилось:
class Counter:
def __init__(self, n):
self.n = n
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
self.i += 1
return self.i
Для 99% задач вариант с yield короче и без багов.
Николай Дмитриевич yield рулит, ручной __next__ почти никогда не нужен · 1 месяц назад
Снежана Пономарёва Только учти: если __iter__ возвращает self, повторно по объекту не пройдёшься — он "исчерпается" · 23 дня назад
9
Достаточно __iter__. Проще всего сделать его генератором с yield — тогда __next__ не нужен вообще.
Ваш ответ
Войдите, чтобы ответить на вопрос.