Генераторные выражения в Python
В этой статье вы узнаете, как использовать генераторные выражения в Python для создания объектов-генераторов.
Генераторное выражение — это выражение, которое возвращает объект-генератор.
Напомним, что генераторная функция — это функция, которая содержит оператор yield
и возвращает объект-генератор.
Например, ниже — генераторная функция:
def squares(length):
for n in range(length):
yield n ** 2
Генераторная функция squares()
возвращает объект-генератор, который вычисляет квадраты чисел от 0
до length - 1
.
Поскольку объект-генератор является итератором, вы можете использовать цикл for для перебора его элементов:
for square in squares(5):
print(square)
Вывод
0 1 4 9 16
Генераторное выражение предоставляет более простой способ возвращать объект-генератор.
Давайте создадим генераторное выражение, которое возвращает квадраты целых чисел чисел от 0 до 4:
squares = (n** 2 for n in range(5))
Поскольку squares
— это объект-генератор, его элементы можно перебрать следующим образом:
for square in squares:
print(square)
Как вы видите, вместо функции для определения генераторной функции можно использовать генераторное выражение.
Генераторное выражение по синтаксису похоже на списковое включение. Например, генераторное выражение тоже поддерживает такие сложные синтаксисы, как:
- операторы if;
- многократные вложенные циклы;
- вложенные включения.
Однако в генераторном выражении вместо квадратных скобок []
используются круглые скобки ()
.
Отличия генераторных выражений от списковых включений
Давайте используем списковое включение для генерации квадратов от 0 до 4:
square_list = [n** 2 for n in range(5)]
Сделаем то же самое с помощью генераторного выражения:
square_generator = (n** 2 for n in range(5))
А теперь разберем, в чем отличия.
1) Синтаксис
Здесь все просто: в генераторном выражении используются квадратные скобки []
, а при списковом включении — круглые скобки ()
.
2) Работа с памятью
Списковое включение возвращает список, а генераторное выражение возвращает объект-генератор.
Это означает, что списковое включение возвращает полный список элементов сразу. А генераторное выражение возвращает список элементов, по одному за раз, на основе запроса.
То есть списковое включение создает все элементы сразу и загружает их в память.
А генераторное выражение создает один элемент на основе запроса. Оно загружает в память только один единственный элемент.
3) Итерируемые объекты vs итераторы
Списковое включение возвращает итерируемый объект. Это означает, что вы можете повторять итерации над результатом спискового включения снова и снова.
А вот генераторное выражение возвращает «ленивый» итератор. Он «исчерпываетс», когда вы завершаете над ним итерацию.