← Все вопросы

Как сделать свой класс итерируемым, чтобы по нему работал for ?

Задан 1 месяц назад504 просмотров2 ответа
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__ не нужен вообще.

Ваш ответ

Войдите, чтобы ответить на вопрос.
Поддержать проект