На этом шаге мы рассмотрим реализацию итерации.
Вы создали нестандартный объект-контейнер, который внутри содержит список, кортеж или какой-то другой итерируемый объект. Вы хотите заставить ваш новый контейнер работать с итерациями.
В типичном случае вам нужно определить метод __iter__(), который делегирует итерацию внутреннему содержимому контейнера. Например:
class Node: def __init__(self, value): self._value = value self._children = [] def __repr__(self): return 'Node({!r})'.format(self._value) def add_child(self, node): self._children.append(node) def __iter__(self): return iter(self._children) # Пример if __name__ == '__main__': root = Node(0) child1 = Node(1) child2 = Node(2) root.add_child(child1) root.add_child(child2) # Выводит Node(1), Node(2) for ch in root: print(ch)
В этой программе метод __iter__() просто перенаправляет запрос на итерацию содержащемуся внутри атрибуту _children.
Протокол итераций Python требует, чтобы __iter__() возвращал специальный объект-итератор, в котором реализован метод __next__(), который и выполняет итерацию. Если вы просто итерируете по содержимому другого контейнера, вам не стоит беспокоиться о деталях внутреннего механизма процесса. Вам нужно просто передать запрос на итерацию.
Использование функции iter() здесь позволяет "срезать путь" и написать более чистый код. Конструкция iter(s) просто возвращает внутренний итератор, вызывая s.__iter__(), - примерно так же, как len(s) вызывает s.__len__().
На следующем шаге мы рассмотрим создание новых итерационных паттернов с помощью генераторов.