Перейти до основного вмісту
Модуль 6 · Урок 3 із 423/36 у курсі~10 min
Модульні уроки (3/4)

Вираз-генератор

Вираз генератора схожий на розуміння списку, але з дужки замість квадратних дужок. Різниця кардинальна: він не створює список у пам’яті, він створює елементи на вимогу, один за одним.

Python
gen = (n * n for n in range(1_000_000))
# istantaneo, memoria costante: nessun calcolo ancora fatto

list_comp = [n * n for n in range(1_000_000)]
# alloca 1M di int in memoria

Лінь (лінива оцінка)

Генератор нічого не робить, поки хтось не запитає наступне значення:

Python
gen = (n * n for n in range(5))
next(gen)    # 0    (calcolato adesso)
next(gen)    # 1
next(gen)    # 4
# ... e così via, fino a StopIteration

Він виснажується: після споживання всіх елементів він порожній назавжди. Щоб використовувати його повторно, ви повинні створити його заново.

Коли це використовувати

Коли ви передаєте результати функції, яка споживає їх послідовно:

Python
total = sum(n * n for n in range(1_000_000))
# nessuna lista intermedia, memoria costante

sum, any, all, max, min, "".join(...) всі приймають генератори. Якщо для зовнішньої функції потрібні лише круглі дужки виклику, ви можете пропустити власний генератор:

Python
sum((n * n for n in range(10)))    # OK
sum(n * n for n in range(10))      # IDENTICO, più leggibile

any та all: коротке замикання

any(...) та all(...) припиняють ітерацію, щойно отримають відповідь. За допомогою генератора наступні елементи навіть не обчислюються.

Python
nums = [1, 2, 3, 4, 5]
any(n > 3 for n in nums)    # True (si ferma a 4)
all(n > 0 for n in nums)    # True
all(n > 2 for n in nums)    # False (si ferma a 1)

Візерунок: відкладений конвеєр

Python
righe = (linea.strip() for linea in testo.splitlines())
non_vuote = (r for r in righe if r)
prime_dieci = []
for r in non_vuote:
    prime_dieci.append(r)
    if len(prime_dieci) == 10:
        break

Немає проміжного списку, навіть на великих входах.

Споживаючі генератори з sum, any, all

Вирази-генератори ідеально підходять для безпосередньої передачі функціям, які використовують ітеровані елементи, наприклад sum(), any() або all(). У цьому випадку ви можете опустити зовнішні дужки виразу генератора, просто написавши:

Python
squares_sum = sum(x**2 for x in range(10))

Це забезпечує чистоту вашого коду та високу ефективність пам’яті.

Спробуйте

вправи#python.m6.l3.e1
Спроби: 0Завантаження…

Обчисліть суму квадратів чисел від 1 до 100 (включно), використовуючи генераторний вираз у sum(). Призначте його до `tot`. Оцініть `tot`.

Завантаження редактора…
Показати підказку

діапазон (1, 101) включає 100.

Рішення доступне після 3 спроб

Повторна вправа

вправи#python.m6.l3.e2
Спроби: 0Завантаження…

Враховуючи `words = ['ciao', 'mondo', 'PYTHON', 'java']`, використовуйте any() із виразом генератора, щоб перевірити, чи ПРИМЕНШЕ одне слово є верхнім регістром (.isupper()). Призначте результат `has_uppercase`. Оцініть `has_uppercase`.

Завантаження редактора…
Показати підказку

any(p.isupper() для p словами)

Рішення доступне після 3 спроб

Додатковий виклик

вправи#python.m6.l3.e3
Спроби: 0Завантаження…

Use a generator expression passed directly to the `sum()` function to calculate the sum of the squares of all integers from 1 to 100 inclusive. Store the result in `total_sum` and evaluate it.

Завантаження редактора…
Показати підказку

Запишіть total_sum = sum(x**2 for x in range(1, 101)). Подвійні дужки не потрібні.

Рішення доступне після 3 спроб