Skip to content

Generator expressions - Генераторные Выражения

Генераторные выражения (generator expressions) - это мощный и элегантный инструмент в Python, позволяющий создавать итераторы "на лету", без необходимости определения полноценной функции-генератора. Они предоставляют компактный синтаксис для создания последовательностей значений, которые вычисляются по требованию, экономя память и повышая эффективность кода.

Что такое генераторные выражения?

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

Синтаксис:

python
(expression for item in iterable)
  • expression: Выражение, которое вычисляется для каждого элемента.
  • item: Переменная, представляющая текущий элемент из iterable.
  • iterable: Итерируемый объект (список, кортеж, строка и т.д.), по которому происходит итерация.

Обычный цикл:

python
numbers = [1, 2, 3, 4, 5]
squares = []
for number in numbers:
  squares.append(number ** 2)
print(squares)  # Output: [1, 4, 9, 16, 25]

Генераторное выражение:

python
numbers = [1, 2, 3, 4, 5]
squares = (number ** 2 for number in numbers)
print(squares) # Output: <generator object <genexpr> at 0x...>
print(list(squares)) # Output: [1, 4, 9, 16, 25]

В примере с генераторным выражением, переменная squares содержит не список, а объект-генератор. Что бы получить список, необходимо сгенерировать все значения, например, преобразовав генератор в список с помощью list(squares).

Упражнения:

  1. Напишите генераторное выражение, которое генерирует кубы чисел от 1 до 10.
  2. Напишите генераторное выражение, которое генерирует длины строк в списке words = ["apple", "banana", "cherry"].
  3. Напишите функцию, которая принимает список строк и возвращает генератор, который выдает длины этих строк.

Генераторные выражения с условием (if-else)

Можно добавить условие с помощью if-else внутри генераторного выражения для выбора различных выражений в зависимости от выполнения условия.

Синтаксис:

python
(expression_1 if condition else expression_2 for item in iterable)
  • expression: Выражение, которое вычисляется для каждого элемента.
  • item: Переменная, представляющая текущий элемент из iterable.
  • iterable: Итерируемый объект (список, кортеж, строка и т.д.), по которому происходит итерация.
  • if condition else (необязательно): Условие, для выбора различных выражений.

Обычный цикл:

python
numbers = [1, 2, 3, 4, 5]
results = []
for number in numbers:
  if number % 2 == 0:
    results.append("четное")
  else:
    results.append("нечетное")
print(results)  # Output: ['нечетное', 'четное', 'нечетное', 'четное', 'нечетное']

Генераторное выражение:

python
numbers = [1, 2, 3, 4, 5]
results = ("четное" if number % 2 == 0 else "нечетное" for number in numbers)
print(list(results))  # Output: ['нечетное', 'четное', 'нечетное', 'четное', 'нечетное']

Упражнения:

  1. Напишите генераторное выражение, которое генерирует "положительное", "отрицательное" или "ноль" для чисел от -5 до 5.
  2. Напишите генераторное выражение, которое генерирует квадраты чисел от 1 до 10, если число четное, и кубы, если число нечетное.
  3. Напишите генераторное выражение, которое генерирует строку "длинное", если длина строки больше 5 символов, и "короткое" в противном случае, для списка words = ["apple", "banana", "cherry", "grape"].
  4. Напишите функцию, которая принимает список чисел и возвращает генератор, который выдает "положительное", "отрицательное" или "ноль" для каждого числа.
  5. Создайте генераторное выражение, которое для чисел от 1 до 30 возвращает "делится на 3", если число делится на 3, и "не делится" в противном случае.

Генераторные выражения с фильтром (if)

Можно фильтровать элементы в генераторном выражении, используя условие if после цикла.

Синтаксис:

python
(expression for item in iterable if condition)
  • expression: Выражение, которое вычисляется для каждого элемента.
  • item: Переменная, представляющая текущий элемент из iterable.
  • iterable: Итерируемый объект (список, кортеж, строка и т.д.), по которому происходит итерация.
  • if condition (необязательно): Условие, которое фильтрует элементы из iterable.

Обычный цикл:

python
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = []
for number in numbers:
  if number % 2 == 0:
    even_numbers.append(number)
print(even_numbers)  # Output: [2, 4, 6]

Генераторное выражение:

python
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = (number for number in numbers if number % 2 == 0)
print(list(even_numbers))  # Output: [2, 4, 6]

Упражнения:

  1. Создайте генераторное выражение, которое возвращает только положительные числа из списка.
  2. Напишите генераторное выражение, которое генерирует числа от 1 до 100, делящиеся на 7.
  3. Напишите генераторное выражение, которое генерирует квадраты чисел от 1 до 20, которые не делятся на 3.
  4. Напишите функцию, которая принимает строку и возвращает генератор, который выдает только гласные буквы.
  5. Создайте генераторное выражение, которое возвращает числа, делящиеся на 5, из диапазона от 1 до 50.

Генераторные выражения с вложенными циклами

Можно использовать вложенные циклы в генераторных выражениях для создания комбинаций элементов из нескольких итерируемых объектов.

Синтаксис:

python
(expression for item_1 in iterable_1 for item_2 in iterable_2)

Обычный цикл:

python
numbers = [1, 2]
letters = ['a', 'b']
combinations = []
for number in numbers:
  for letter in letters:
    combinations.append((number, letter))
print(combinations)  # Output: [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]

Генераторное выражение:

python
numbers = [1, 2]
letters = ['a', 'b']
combinations = ((number, letter) for number in numbers for letter in letters)
print(list(combinations))  # Output: [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]

Упражнения:

  1. Напишите генераторное выражение, которое генерирует все возможные пары чисел от 1 до 3 и букв 'a', 'b', 'c'.
  2. Напишите генераторное выражение, которое генерирует все возможные комбинации элементов из списка colors = ["red", "green", "blue"] и списка shapes = ["circle", "square"].
  3. Напишите генераторное выражение, которое генерирует все возможные произведения чисел от 1 до 3 и чисел от 4 до 6.
  4. Создайте генераторное выражение, которое генерирует все пары (x, y) для x из [1, 2] и y из ['A', 'B'].

Генераторные выражения с вложенными циклами и условиями

Можно комбинировать вложенные циклы с условиями для создания более сложных генераторных выражений.

Синтаксис:

python
(expression for item_1 in iterable_1 if condition for item_2 in iterable_2 if condition)

Можно добавить больше вложенных циклов с условиями.

Обычный цикл:

python
numbers1 = [1, 2, 3]
numbers2 = [4, 5, 6]
pairs = []
for num1 in numbers1:
  if num1 % 2 == 0:
    for num2 in numbers2:
      if num2 % 2 != 0:
        pairs.append((num1, num2))
print(pairs) # Output: [(2, 5)]

Генераторное выражение:

python
numbers1 = [1, 2, 3]
numbers2 = [4, 5, 6]
pairs = ((num1, num2) for num1 in numbers1 if num1 % 2 == 0 
                     for num2 in numbers2 if num2 % 2 != 0)
print(list(pairs)) # Output: [(2, 5)]

Упражнения:

  1. Напишите генераторное выражение, которое генерирует пары чисел из списка numbers1 = [1, 2, 3, 4] и numbers2 = [5, 6, 7, 8], где первое число четное, а второе - нечетное.
  2. Напишите генераторное выражение, которое генерирует тройки чисел из списков numbers1 = [1, 2, 3], numbers2 = [4, 5, 6], numbers3 = [7, 8, 9], где сумма первого и второго числа меньше 8, а третье число делится на 3.
  3. Напишите генераторное выражение, которое генерирует строки, состоящие из комбинаций букв из letters1 = ['a', 'b'] и letters2 = ['c', 'd'], где первая буква гласная ('a'), а вторая - согласная ('c','d').
  4. Создайте генераторное выражение, которое генерирует пары (x, y) для четных x из [1, 2, 3, 4] и y из ['A', 'B'] только для y = 'A'.
  5. Напишите функцию, которая принимает список чисел и список строк, возвращает генератор пар (число, строка), где число четное и строка начинается с 'b'.
  6. Создайте генераторное выражение, которое генерирует все комбинации (x, y) для четных x из [1, 2, 3, 4] и y из ['x', 'y', 'z'], где y равно 'y'.
  7. Напишите генераторное выражение, которое генерирует все числа от 1 до 100, которые являются простыми числами.

Преимущества генераторных выражений:

  • Экономия памяти: Генераторные выражения не создают всю последовательность значений сразу, а генерируют их по требованию. Это особенно полезно при работе с большими объемами данных, когда создание полного списка может привести к переполнению памяти.
  • Ленивые вычисления (Lazy Evaluation): Значения вычисляются только тогда, когда они нужны. Это может значительно повысить производительность, особенно если не все значения из последовательности потребуются.
  • Бесконечные последовательности: Можно создавать генераторы, которые генерируют бесконечные последовательности, что невозможно с list comprehension.

Contacts: teffal@mail.ru