232 Глава 6 •
Циклы и итерации
няют шаблоны проектирования в своих программах, у создателей языков
растет стимул предлагать абстракции и укороченные пути их реализации.
Именно так происходит эволюция языков, и, как разработчики, мы полу-
чаем от этого выгоду. Мы приступаем к работе со все более и более мощ-
ными структурными блоками, которые сокращают бесполезную рутину
и позволяют достигать большего за меньшее время.
Ранее в этой книге вы увидели, как генераторы предлагают синтаксиче-
ский сахар для написания итераторов на основе класса.
Выражения-гене-
раторы (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)
Разве не удивительно, что однострочное выражение-генератор теперь де-
лает работу, для выполнения которой ранее требовалась четырехстрочная
функция-генератор или намного более длинный итератор на основе класса?
Но я бегу впереди паровоза. Давайте убедимся, что наш итератор, опре-
деленный при помощи выражения-генератора, действительно работает
как ожидалось:
6 .6 . Выражения-генераторы
233
>>> iterator = ('Привет' for i in range(3))
>>> for x in iterator:
... print(x)
'Привет'
'Привет'
'Привет'
Как по мне, смотрится весьма неплохо! Из нашего однострочного выра-
жения-генератора мы, похоже, получили те же самые результаты, которые
мы получали из
функции-генератора
bounded_repeater
.
Правда, есть одно маленькое предостережение: после того как выраже-
ние-генератор было использовано, оно не может быть перезапущено или
использовано снова. Поэтому в некоторых случаях предпочтительнее
использовать функции-генераторы или итераторы на основе класса.
Выражения-генераторы
против включений в список
Как вы уже поняли, выражения-генераторы несколько напоминают вклю-
чения в список:
>>> listcomp = ['Привет' for i in range(3)]
>>> genexpr = ('Привет' for i in range(3))
Однако в отличие от включений в список выражения-генераторы не
конструируют объекты-списки. Вместо этого они генерируют значения
«точно в срок» подобно тому, как это сделал бы итератор на основе класса
или функция-генератор.
Присваивая выражение-генератор переменной, вы просто получите ите-
рируемый «объект-генератор»:
>>> listcomp
['Привет', 'Привет', 'Привет']
>>> genexpr
at 0x1036c3200>
234 Глава 6 • Циклы и итерации
Для того чтобы получить доступ к значениям, порожденным выражением-
генератором, вам нужно вызвать с ним метод
next()
точно так же, как вы
бы сделали с любым другим итератором:
>>> next(genexpr)
Do'stlaringiz bilan baham: