Модульні уроки (3/4)
Вираз-генератор
Вираз генератора схожий на розуміння списку, але з дужки замість квадратних дужок. Різниця кардинальна: він не створює список у пам’яті, він створює елементи на вимогу, один за одним.
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Лінь (лінива оцінка)
Генератор нічого не робить, поки хтось не запитає наступне значення:
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Він виснажується: після споживання всіх елементів він порожній назавжди. Щоб використовувати його повторно, ви повинні створити його заново.
Коли це використовувати
Коли ви передаєте результати функції, яка споживає їх послідовно:
total = sum(n * n for n in range(1_000_000))
# nessuna lista intermedia, memoria costantesum, any, all, max, min, "".join(...) всі приймають генератори.
Якщо для зовнішньої функції потрібні лише круглі дужки виклику, ви можете
пропустити власний генератор:
sum((n * n for n in range(10))) # OK
sum(n * n for n in range(10)) # IDENTICO, più leggibileany та all: коротке замикання
any(...) та all(...) припиняють ітерацію, щойно отримають відповідь.
За допомогою генератора наступні елементи навіть не обчислюються.
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)Візерунок: відкладений конвеєр
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(). У цьому випадку ви можете опустити зовнішні дужки виразу генератора, просто написавши:
squares_sum = sum(x**2 for x in range(10))Це забезпечує чистоту вашого коду та високу ефективність пам’яті.
Спробуйте
Обчисліть суму квадратів чисел від 1 до 100 (включно), використовуючи генераторний вираз у sum(). Призначте його до `tot`. Оцініть `tot`.
Показати підказку
діапазон (1, 101) включає 100.
Рішення доступне після 3 спроб
Повторна вправа
Враховуючи `words = ['ciao', 'mondo', 'PYTHON', 'java']`, використовуйте any() із виразом генератора, щоб перевірити, чи ПРИМЕНШЕ одне слово є верхнім регістром (.isupper()). Призначте результат `has_uppercase`. Оцініть `has_uppercase`.
Показати підказку
any(p.isupper() для p словами)
Рішення доступне після 3 спроб
Додатковий виклик
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 спроб