Python итератор итерируемый объект

Итераторы и итерируемые объекты в Python

Итератор — это объект, с помощью которого можно перебирать коллекции. Для этого у итератора должны быть следующие методы:

Когда вы завершаете перебор коллекции с помощью итератора, он «исчерпывается». Это означает, что больше тот итератор использовать нельзя.

Итерируемые объекты

Итерируемый объект — это объект, который можно перебирать.

Объект является итерируемым, если он реализует метод __iter__ , который возвращает новый итератор.

Встроенные списки и итератор списков

Cписок — это упорядоченная коллекция элементов. Он является итерируемым объектов, поскольку у него есть метод __iter__ , который возвращает итератор. Например:

numbers = [1, 2, 3] number_iterator = numbers.__iter__() print(type(number_iterator))

В этом примере метод __iter__ возвращает итератор типа list_iterator .

Поскольку list_iterator реализует метод __iter__ , вы можете использовать встроенную функцию iter() для получения объекта итератора:

numbers = [1, 2, 3] number_iterator = iter(numbers)

Поскольку у list_iterator также есть метод __next__ , вы можете использовать встроенную функцию next() для перебора списка:

numbers = [1, 2, 3] number_iterator = iter(numbers) next(number_iterator) next(number_iterator) next(number_iterator)

Если вызвать эту функцию еще раз, вы получите ошибку StopIteration.

next(number_iterator) # ошибка StopIteration

Так происходит потому, что итератор списка был исчерпан. Чтобы повторить итерацию списка, необходимо создать новый итератор.

Это иллюстрирует разницу между списком и его итератором. Список создается один раз, а итератор создается каждый раз, когда вам нужно выполнить перебор списка.

Итераторы и итерируемые объекты

Давайте создадим класс Colors :

class Colors: def __init__(self): self.rgb = ['красный', 'зеленый', 'синий'] self.__index = 0 def __iter__(self): return self def __next__(self): if self.__index >= len(self.rgb): raise StopIteration # возвращаем следующий цвет color = self.rgb[self.__index] self.__index += 1 return color

В этом примере класс Colors играет две роли. Он одновременно является итератором и итерируемым объектом.

Читайте также:  Android java select directory

Класс Colors является итератором, поскольку в нем реализованы методы __iter__ и __next__ . Метод __iter__ возвращает сам объект, а __next__ возвращает следующий элемент из списка.

Класс Colors является итерабельным, поскольку реализует метод __iter__ , который возвращает сам объект, являющийся итератором.

Давайте создадим новый экземпляр класса Colors и выполним перебор его элементов с помощью цикла for:

colors = Colors() for color in colors: print(color)

После завершения перебора объект colors становится бесполезным. Если вы попытаетесь повторить итерацию, вы получите исключение StopIteration:

next(colors) # ошибка StopIteration

Если вы по новой запустите цикл for, вы ничего не получите, потому что итератор исчерпан:

for color in colors: print(color)

Чтобы повторить перебор, необходимо создать новый объект colors с атрибутом rgb . Но это неэффективно.

Различаем итераторы и итерируемые объекты

Давайте отделим итератор color от итерабельного объекта color , как это делает Python с итератором списка и списком.

class Colors: def __init__(self): self.rgb = ['красный', 'зеленый', 'синий'] def __len__(self): return len(self.rgb)

Теперь создадим класс ColorsIterator :

class ColorIterator: def __init__(self, colors): self.__colors = colors self.__index = 0 def __iter__(self): return self def __next__(self): if self.__index >= len(self.__colors): raise StopIteration # возвращаем следующий цвет color = self.__colors.rgb[self.__index] self.__index += 1 return color

Как это работает

  • Метод __init__ принимает итератор, который является экземпляром класса Colors .
  • Метод __iter__ возвращает сам итератор.
  • Метод __next__ возвращает следующий элемент из объекта Colors .

Теперь покажем, как использовать ColorIterator для перебора объекта Colors :

colors = Colors() color_iterator = ColorIterator(colors) for color in color_iterator: print(color)

Для повторного перебора объекта Colors достаточно создать новый экземпляр ColorIterator .

Когда вы хотите перебрать объект Colors, вам нужно вручную создать новый объект ColorIterator . При этом нужно запомнить имя итератора ColorIterator .

Читайте также:  Узнать версию python debian

Было бы здорово автоматизировать этот процесс. Для этого можно сделать класс Colors итерируемым объектом, реализовав метод __iter__ . Давайте это и сделаем:

class Colors: def __init__(self): self.rgb = ['красный', 'зеленый', 'синий'] def __len__(self): return len(self.rgb) def __iter__(self): return ColorIterator(self) 

Метод __iter__ возвращает новый экземпляр класса ColorIterator .

Теперь вы можете выполнять перебор объекта Colors без явного создания объекта ColorIterator :

colors = Colors() for color in colors: print(color) 

Внутри цикла for вызывается метод __iter__ объекта colors для получения итератора. Он используется для перебора элементов объекта colors .

Давайте поместим класс ColorIterator в класса Colors , чтобы инкапсулировать их в один класс:

class Colors: def __init__(self): self.rgb = ['красный', 'зеленый', 'синий'] def __len__(self): return len(self.rgb) def __iter__(self): return self.ColorIterator(self) class ColorIterator: def __init__(self, colors): self.__colors = colors self.__index = 0 def __iter__(self): return self def __next__(self): if self.__index >= len(self.__colors): raise StopIteration # возвращаем следующий цвет color = self.__colors.rgb[self.__index] self.__index += 1 return color 

Что нужно запомнить

  • Итерируемый объект — это объект с методом __iter__ , который возвращает итератор.
  • Итератор — это объект с методом __iter__ , который возвращает самого себя, и методом __next__ , который возвращает следующий элемент.
  • Итераторы также являются итерируемыми объектами. Однако они «исчерпываются», а итерируемые объекты — нет.

СodeСhick.io — простой и эффективный способ изучения программирования.

2023 © ООО «Алгоритмы и практика»

Источник

Оцените статью