Страницы

Поиск по вопросам

вторник, 24 декабря 2019 г.

Зачем нужен __iter__, когда есть __next__?

#python #python_3x #классы #итераторы #дизайн_языка


Я учу python и у меня возник вопрос по итераторам.
Чтобы можно было итерироваться по объекту, у него должен быть метод __iter__, который
вернет объект-итератор.
У объекта-итератора должен быть метод __next__, который будет возвращать следующий
элемент из объекта, по которому итерируемся, либо кидать ошибку StopIteration.
Я встречал только такой код, в котором __iter__ возвращает self.
Например 

class RandomIterator:
    def __iter__(self):
        return self

    def __init__(self, k):
        self.k = k
        self.i = 0

    def __next__(self):
        if self.i < self.k:
            self.i += 1
            return random()
        else:
            raise StopIteration


Вот у меня и возник вопрос, какой смысл от метода __iter__?
    


Ответы

Ответ 1



__iter__() в Python Как вы узнали из урока «Классы и объекты Python», у всех классов есть функция под названием __init__(), которая позволяет вам делать инициализацию при создании объекта. Метод __iter__() действует аналогично, вы можете выполнять операции (инициализацию и т. Д.), Но всегда должны возвращать сам объект итератора. немного хабра Теперь, когда речь зашла о создании собственных последовательностей в Питоне, пришло время поговорить о протоколах. Протоколы немного похожи на интерфейсы в других языках тем, что они предоставляют набор методов, которые вы должны реализовать. Однако, в Питоне протоколы абсолютно ни к чему не обязывают и не требуют обязательно реализовать какое-либо объявление. Наверное, они больше похожи на руководящие указания. Почему мы заговорили о протоколах? Потому, что реализация произвольных контейнерных типов в Питоне влечёт за собой использование некоторых из них. Во-первых, протокол для определения неизменяемых контейнеров: чтобы создать неизменяемый контейнер, вы должны только определить __len__ и __getitem__ (продробнее о них дальше). Протокол изменяемого контейнера требует того же, что и неизменяемого контейнера, плюс __setitem__ и __delitem__. И, наконец, если вы хотите, чтобы ваши объекты можно было перебирать итерацией, вы должны определить __iter__, который возвращает итератор. Этот итератор должен соответствовать протоколу итератора, который требует методов __iter__(возвращает самого себя) и next. __iter__(self) Должен вернуть итератор для контейнера. Итераторы возвращаются в множестве ситуаций, главным образом для встроенной функции iter() и в случае перебора элементов контейнера выражением for x in container:. Итераторы сами по себе объекты и они тоже должны определять метод __iter__, который возвращает self. UPDATE (вернул пример с кодом, ибо попросили в комментах): Вот в примере по 1-й ссылке есть один из вариантов зачем. Когда вам нужно считать кол-во элеметов обработанных или иные связанные операции. Это полезно для уменьшения кол-во дублирования кода (см. принципы языка Python)iter() в Python class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): x = self.a self.a += 1 return x А вот ниже мой пример использования __iter__ class Fibbonachi: def __iter__(self): self.cur_val = 0 self.next_val = 1 return self def __next__(self): tmp = self.next_val self.next_val += self.cur_val self.cur_val = tmp return tmp for i in Fibbonachi(): print(i) if i > 100: break # Результат: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 в колонку

Комментариев нет:

Отправить комментарий