Сообщить об ошибке.

Функция iter() создает итератор из последовательности

Синтаксис:

iter(object, sentinel)

Параметры:

  • object - последовательность или итератор,
  • sentinel - значение с которым будет вызываться каждый элемент из object (если элементы object - это вызываемые объекты).

Возвращаемое значение:

  • iterator - объект итератора.

Описание:

Функция iter() возвращает объект итератора. Первый аргумент object интерпретируется по-разному, в зависимости от наличия второго аргумента sentinel.

Если НЕТ аргумента sentinel, то первый аргумент object должен быть объектом-коллекцией, которая поддерживает протокол итераций метод __iter__() или он должен поддерживать протокол последовательности метод __getitem__() с целыми аргументами, начиная с 0. Если он не поддерживает любой из этих протоколов, бросается исключение TypeError.

Если передается аргумент sentinel, то ожидается, что первый аргумент object, поддерживает вызов __call__(). В этом случае, созданный итератор будет вызывать указанный объект с каждым обращением к своему __next__() и проверять полученное значение на равенство со значением, переданным в аргумент sentinel. Если полученное значение равно sentinel, то бросается исключение StopIteration, иначе возвращается полученное значение.

Встроенная функция iter с двумя аргументами более или менее эквивалентна этой функции-генератору:

def iter(func, target_value):
    while target_value != (value := func()):
        yield value

Примеры создания итератора из последовательностей.

x = iter(["apple", "banana", "cherry"])
print(next(x))
print(next(x))
print(next(x))

Одно из применений второго аргумента sentinel это чтение строк файла, пока не будет достигнута, переданная в sentinel. Следующий пример считывает файл, пока метод readline() не вернёт пустую строку:

with open('mydata.txt') as fp:
    # читаем, пока не попадется пустая строка
    for line in iter(fp.readline, sentinel=''): 
        # Делаем что-то с line.

Пользовательский тип, определивший __call__():

class MyIterable(object):
    def __init__(self):
        self.index = 0
        self.items = [1, 2, 3, 4]

    def __call__(self):
        value = self.items[self.index]
        self.index += 1
        return value


x = iter(MyIterable(), 3)

print(next(x))  # 1
print(next(x))  # 2
print(next(x))  # StopIteration

Создание итератора из функции

Версия iter(function, value) создаст итератор, который возвращает последовательные возвращаемые значения вызова function пока одно из них не совпадет с value, после чего итератор завершается. Например, используя функцию input, можно создать цикл, который будет печатать текст по нажатию Enter и будет делать это до тех пор пока пользователь не введет exit.

for user_str in iter(input, "exit"):
    # Обработка ввода пользователя...
    print(f"Пользователь ввел {user_str!r}.")

Чтобы увидеть цикл в действии, скопируйте и вставьте приведенный выше код в интерпретатор и введите пару строк.

В документации показан еще один пример использования iter этого способа для создания "считывателя фрагментов", например, для чтения фрагментов из сокета:

from functools import partial

for block in iter(partial(sock.recv, 64), b""):
    # Блок 64 байта...

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

Другой пример использования - в контексте симуляций, где необходимо запустить симуляцию, пока случайное число не достигнет определенного значения. Например, бросание кубика, пока не выпадет число 6:

from random import randint

def roll():
    return randint(1, 10)

for die_roll in iter(roll, 6):
    # процесс бросания.
    print(die_roll)

print('Выпало число 6')

Помним, что тип итератора iterator "кончаем", т.е. он исчерпывается/заканчивается и для повторной итерации его нужно снова инициировать.