Введение в язык Питон

         

Фабрики базовых итераторов


Все функции в модуле itertools могут быть легко реализованы на чистом Python как генераторы. Основной смысл этого модуля в Python 2.3+ - обеспечить стандартное поведение и имена для некоторых полезных функций. Хотя программисты могли бы написать свои собственные версии, на практике каждый создал бы слегка несовместимые вариации. Помимо этого, еще одна причина - эффективная реализация итераторных комбинаторов на С. Использование функций itertools будет заметно быстрее, чем написание своих собственных комбинаторов. В стандартной документации показаны эквивалентные реализации на чистом Python для каждой функции itertools, так что нет необходимости повторять их в этой статье.

Функции в модуле itertools настолько базовые - и достаточно четко поименованные - что, вероятно, имеет смысл импортировать все имена из этого модуля. Функция enumerate(), например, вполне могла бы существовать в itertools, но вместо этого является встроенной функцией в Python 2.3+. В частности, вы можете легко выразить enumerate() в терминах функций itertools:

    from itertools import * enumerate = lambda iterable: izip(count(), iterable)

Давайте рассмотрим несколько функций itertools, которые не используют другие итераторы в качестве базиса, а просто создают итераторы "с нуля". times() возвращает итератор, который выдает идентичный объект множество раз; сама по себе эта возможность довольно удобна, но по-настоящему она хороша при избыточном использовании xrange() и индексной переменной для простого повторения действия. То есть вместо:

    for i in xrange(1000): do_something()

Вы можете теперь использовать более нейтральное:

    for _ in times(1000): do_something()

Если второй аргумент не передается в times(), она просто повторно выдает None. Функция repeat() подобна times(), но неограниченно возвращает тот же самый объект. Этот итератор удобен либо если у цикла имеется независимое условие break, либо в комбинаторах, как izip() и imap().

Функция count() похожа на помесь repeat() и range(). count() неограниченно возвращает последовательно идущие целые (начиная с факультативного аргумента). Однако, с учетом того, что в настоящий момент count() корректно не поддерживает автоматическое преобразование к long при переполнении, вы могли бы с равным успехом по-прежнему использовать xrange(n,sys.maxint); она не является неограниченной буквально, но для большинства целей приводит к тому же. Как и repeat(), count() особенно удобна в других итераторных комбинаторах.



Содержание раздела