Appearance
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 до 10.
- Напишите генераторное выражение, которое генерирует длины строк в списке
words = ["apple", "banana", "cherry"]
. - Напишите функцию, которая принимает список строк и возвращает генератор, который выдает длины этих строк.
Генераторные выражения с условием (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: ['нечетное', 'четное', 'нечетное', 'четное', 'нечетное']
Упражнения:
- Напишите генераторное выражение, которое генерирует "положительное", "отрицательное" или "ноль" для чисел от -5 до 5.
- Напишите генераторное выражение, которое генерирует квадраты чисел от 1 до 10, если число четное, и кубы, если число нечетное.
- Напишите генераторное выражение, которое генерирует строку "длинное", если длина строки больше 5 символов, и "короткое" в противном случае, для списка
words = ["apple", "banana", "cherry", "grape"]
. - Напишите функцию, которая принимает список чисел и возвращает генератор, который выдает "положительное", "отрицательное" или "ноль" для каждого числа.
- Создайте генераторное выражение, которое для чисел от 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 до 100, делящиеся на 7.
- Напишите генераторное выражение, которое генерирует квадраты чисел от 1 до 20, которые не делятся на 3.
- Напишите функцию, которая принимает строку и возвращает генератор, который выдает только гласные буквы.
- Создайте генераторное выражение, которое возвращает числа, делящиеся на 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 до 3 и букв 'a', 'b', 'c'.
- Напишите генераторное выражение, которое генерирует все возможные комбинации элементов из списка
colors = ["red", "green", "blue"]
и спискаshapes = ["circle", "square"]
. - Напишите генераторное выражение, которое генерирует все возможные произведения чисел от 1 до 3 и чисел от 4 до 6.
- Создайте генераторное выражение, которое генерирует все пары (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)]
Упражнения:
- Напишите генераторное выражение, которое генерирует пары чисел из списка
numbers1 = [1, 2, 3, 4]
иnumbers2 = [5, 6, 7, 8]
, где первое число четное, а второе - нечетное. - Напишите генераторное выражение, которое генерирует тройки чисел из списков
numbers1 = [1, 2, 3]
,numbers2 = [4, 5, 6]
,numbers3 = [7, 8, 9]
, где сумма первого и второго числа меньше 8, а третье число делится на 3. - Напишите генераторное выражение, которое генерирует строки, состоящие из комбинаций букв из
letters1 = ['a', 'b']
иletters2 = ['c', 'd']
, где первая буква гласная ('a'), а вторая - согласная ('c','d'). - Создайте генераторное выражение, которое генерирует пары (x, y) для четных x из [1, 2, 3, 4] и y из ['A', 'B'] только для y = 'A'.
- Напишите функцию, которая принимает список чисел и список строк, возвращает генератор пар (число, строка), где число четное и строка начинается с 'b'.
- Создайте генераторное выражение, которое генерирует все комбинации (x, y) для четных x из [1, 2, 3, 4] и y из ['x', 'y', 'z'], где y равно 'y'.
- Напишите генераторное выражение, которое генерирует все числа от 1 до 100, которые являются простыми числами.
Преимущества генераторных выражений:
- Экономия памяти: Генераторные выражения не создают всю последовательность значений сразу, а генерируют их по требованию. Это особенно полезно при работе с большими объемами данных, когда создание полного списка может привести к переполнению памяти.
- Ленивые вычисления (Lazy Evaluation): Значения вычисляются только тогда, когда они нужны. Это может значительно повысить производительность, особенно если не все значения из последовательности потребуются.
- Бесконечные последовательности: Можно создавать генераторы, которые генерируют бесконечные последовательности, что невозможно с list comprehension.