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"кончаем", т.е. он исчерпывается/заканчивается и для повторной итерации его нужно снова инициировать.