На этом шаге мы рассмотрим малоизвестную возможность встроенной функции iter().
У вас есть код, который использует цикл while для итеративной обработки данных, потому что в программе присутствует функция или какое-то необычное проверочное условие, которое нельзя вместить в стандартный итерационный паттерн.
Вполне обычный код для программ, работающих с вводом-выводом:
CHUNKSIZE = 8192 def reader(s): while True: data = s.recv(CHUNKSIZE) if data == b'': break process_data(data)
Такой код часто можно заменить использованием iter(), как показано ниже:
def reader(s): for chunk in iter(lambda: s.recv(CHUNKSIZE), b''): process_data(data)
Если вы сомневаетесь, будет ли это работать, то можете попробовать похожий пример для обработки файлов:
>>> import sys >>> f = open('/etc/passwd') >>> for chunk in iter(lambda: f.read(10), b''): n = sys.stdout.write(chunk) . . . nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false root:*:0:0:System Administrator:/var/root:/bin/sh daemon:*:1:1:System Services:/var/root:/usr/bin/false _uucp:*:4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico . . . >>>
Малоизвестная возможность встроенной функции iter() заключается в том, что она может опционально принимать вызываемый (callable) аргумент и пороговое значение. При таком использовании функция создает итератор, который снова и снова повторяет вызов предоставленного вызываемого объекта, пока он не вернет значение, равное пороговому значению.
Этот конкретный подход хорошо работает с некоторыми типами многократно вызываемых функций, таких как операции ввода-вывода. Например, если вы хотите читать данные кусочками ("chunk") из файлов или сокетов, то обычно должны многократно вызывать read() или recv() с последующей проверкой достижения конца файла. Представленный выше рецепт просто берет эти две функциональности и совмещает в единственном вызове iter(). Использование lambda в решении необходимо для создания вызываемого объекта, который не принимает аргументов, но при этом поставляет аргумент нужного размера в recv() или read().
Со следующего шага мы начнем рассмотривать файлы и ввод-вывод.