Skip to content

Итераторы

Итератор — это объект, который позволяет перебирать элементы коллекции (например, списка или кортежа) по одному за раз. Итераторы используются для экономии памяти и повышения эффективности работы с большими наборами данных.

Итераторы необходимы, когда нужно обрабатывать элементы коллекции по одному, без загрузки всей коллекции в память. Например, при чтении большого файла или обходе элементов базы данных.

Итераторы реализуются работой двух функций:

iter(): Возвращает сам итератор. Это метод, который возникает при организации итераций, например, в цикле for.
next(): Возвращает следующий элемент в последовательности. Если элементы закончились, вызывается исключение StopIteration.

Пример использования функций iter() и next(). Когда элементы коллекции заканчиваются, метод __next__() вызывает исключение StopIteration.:

python
numbers = [1, 2, 3]
iterator = iter(numbers)

print(iterator)
print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
print(next(iterator))  # StopIteration

Пример с использованием while:

python
numbers = [1, 2, 3, 4, 5]
iterator = iter(numbers)

while True:
    try:
        number = next(iterator)
    except StopIteration:
        break
    else:
        print(number)

Пример с использованием for:

python
numbers = [1, 2, 3, 4, 5]
for number in iter(numbers):
    print(number)

Встроенные функции, такие как max() и min() могут принимать один аргумент итератора и возвращать наибольший или наименьший элемент. Операторы in и not in также поддерживают итераторы: x in iterator возвращает True, если x найден в потоке, возвращаемом итератором.

Вы столкнетесь с очевидными проблемами, если итератор бесконечен:

  • max() и min(), никогда ничего не вернет,
  • и если элемент x никогда не закончиться в потоке, in и not in операторы также ничего не вернут.

Обратите внимание, что вы можете двигаться только вперед в итераторе: нет способа получить предыдущий элемент, сбросить итератор или сделать его копию. Объекты итератора могут опционально предоставлять эти дополнительные возможности, но протокол итератора определяет только метод __next__(). Поэтому функции могут потреблять весь вывод итератора, и если вам нужно сделать что-то другое с тем же потоком, вам придется создать новый итератор.

python
numbers = [1, 2, 3, 4, 5]

iter_numbers = iter(numbers)

print('\n1 iteration:', end=' ')
for number in iter_numbers:
    print(number, end=', ')

print('\n2 iteration:', end=' ')
for number in iter_numbers:
    print(number, end=', ')

iter_numbers = iter(numbers)
print('\n3 iteration:', end=' ')
for number in iter_numbers:
    print(number, end=', ')

В результат выполнения 2 итератор будет пустым, так как он уже выполнился в предыдущем цикле. Но если итератор создать заново, то можно продолжит итерации:

1 iteration: 1, 2, 3, 4, 5, 
2 iteration: 
3 iteration: 1, 2, 3, 4, 5,

Зачем нужны итераторы?

Итераторы полезны в следующих случаях:

  • Эффективность памяти: Они позволяют обрабатывать данные по одному элементу за раз, что снижает потребление памяти.
  • Универсальность: Итераторы предоставляют единый интерфейс для работы с различными коллекциями и типами данных.
  • Ленивые вычисления: Итераторы позволяют производить вычисления по требованию, не загружая все данные в память сразу.

Когда используются итераторы?

  • Чтение файлов: Вы можете использовать итераторы для чтения файлов построчно, что особенно полезно для работы с большими файлами.
  • Работа с потоками данных: Итераторы удобны для обработки потоков данных, таких как данные из сетевых запросов или генераторов данных.
  • Обработка больших данных: Они позволяют работать с большими наборами данных, загружая в память только необходимые части.

Упражнения:

  1. Создайте список из строк и используйте итератор для вывода каждого элемента.
  2. Создайте список чисел от 1 до 10 и используйте итератор для вывода только четных чисел.
  3. Создайте строку с именами людей, разделенными запятыми. Используйте итератор для вывода только имен, начинающихся с буквы "И".
  4. Напишите функцию, которая принимает итерируемый объект и возвращает список всех его элементов, используя итератор.
  5. Напишите функцию, которая принимает строку и возвращает список всех уникальных символов в ней, используя итератор.
  6. Напишите функцию, которая принимает на вход список и возвращает его элементы в обратном порядке, используя итератор и next().

Типы данных, поддерживающие итераторы

В Python многие встроенные типы данных поддерживают итераторы, включая:

  • Строки (str)
  • Списки (list)
  • Кортежи (tuple)
  • Словари (dict)
  • Множества (set)

Пример использования итераторов с различными типами данных:

python
# string - строка
word = "hello"
for char in word:
    print(char)

# list - список
numbers = [1, 2, 3]
for number in numbers:
    print(number)

# tuple - кортеж
letters = ('a', 'b', 'c')
for letter in letters:
    print(letter)

# dictionary - словарь
fruits = {'apple': 1, 'banana': 2}
for key in fruits:
    print(key, fruits[key])

# set - множество
unique_numbers = {1, 2, 3}
for number in unique_numbers:
    print(number)

Обратите внимание, что начиная с Python 3.7, порядок итерации словаря гарантированно совпадает с порядком вставки. В более ранних версиях поведение не было определено и могло различаться между реализациями.

Применение iter() к словарю всегда проходит по ключам, но у словарей есть методы, которые возвращают другие итераторы. Если вы хотите выполнить итерацию по значениям или парам ключ/значение, вы можете явно вызвать методы values() или items() чтобы получить соответствующий итератор.

Конструктор dict() может принимать итератор, который возвращает конечный поток кортежей: (key, value)

python
list_tuple_country_capitals = [
    ('Brazil', 'Brasilia'), 
    ('Russia', 'Moscow'), 
    ('India', 'New Delhi'), 
    ('China', 'Beijing'), 
    ('South Africa', 'Pretoria, Cape Town, Bloemfontein')
]
print(dict(iter(list_tuple_country_capitals)))
print(dict(list_tuple_country_capitals))

Упражнения:

  1. Напишите программу, которая принимает строку и выводит каждый символ на новой строке, используя итератор.
  2. Создайте словарь и используйте итератор для вывода всех ключей и значений.
  3. Создайте словарь с именами и возрастами людей. Используйте итератор для вывода только имен людей, которым более 30 лет.
  4. Создайте итератор, который генерирует первые n чисел Фибоначчи. Реализуйте это без использования классов.
  5. Используя функцию iter(), создайте бесконечный итератор, который поочередно возвращает элементы из списка [10, 20, 30].

Contacts: teffal@mail.ru