Шаг 155.
Python: тонкости программирования.
Циклы и итерации. Выражения-генераторы (общие сведения)

    На этом шаге мы дадим краткую характеристику выражениям-генераторам.

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

    Дело в том, что итераторы на основе класса и функции-генераторы выражают один и тот же лежащий в основе шаблон проектирования.

    Функции-генераторы предоставляют краткую форму для поддержки протокола итератора в своем собственном коде и по большей части избегают многословности итераторов на основе класса. Благодаря незначительному объему специализированного синтаксиса или "горсти" синтаксического сахара, они экономят время и облегчают вашу жизнь как разработчика.

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

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

    Ранее вы увидели, как генераторы предлагают синтаксический сахар для написания итераторов на основе класса. Выражения-генераторы (generator expressions), которые мы рассмотрим на этом шаге, добавят сверху еще один слой синтаксического сахара.

    Выражения-генераторы представляют собой еще более эффективную краткую форму для создания итераторов. Благодаря простому и сжатому синтаксису, который похож на конструкцию включения в список, вы сможете определять итераторы в одной строке кода.

    Приведем пример:

iterator = ('Привет' for i in range(3))

    Во время выполнения итераций данное выражение-генератор порождает ту же самую последовательность значений, что и функция-генератор bounded_repeater(), которую мы написали в предыдущем разделе. Ниже приведем ее снова, чтобы освежить вашу память:

>>> def bounded_repeater(value, max_repeats):
	for i in range(max_repeats):
		yield value

>>> iterator = bounded_repeater('Привет', 3)

    Разве не удивительно, что однострочное выражение-генератор теперь делает работу, для выполнения которой ранее требовалась четырехстрочная функция-генератор или намного более длинный итератор на основе класса?

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

>>> iterator = ('Привет' for i in range(3))
>>> for x in iterator:
	print(x)

	
Привет
Привет
Привет

    Смотрится весьма неплохо! Из нашего однострочного выражения-генератора мы, похоже, получили те же самые результаты, которые мы получали из функции-генератора bounded_repeater().

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

    На следующем шаге мы сравним выражения-генераторы и включения в список.




Предыдущий шаг Содержание Следующий шаг