モジュールのレッスン (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 memoriaLazyness (遅延評価)
ジェネレーターは、誰かが次の値を要求するまで何も行いません。
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))これにより、コードがクリーンになり、メモリ効率が高くなります。
試してみてください
sum() 内のジェネレーター式を使用して、1 から 100 (両端を含む) までの数値の二乗和を計算します。それを「tot」に代入します。 「tot」を評価します。
ヒントを表示
range(1, 101) には 100 が含まれます。
3 回の試行後に解決策が利用可能になります
復習演習
`words = ['ciao', 'mondo', 'PYTHON', 'java']` とすると、ジェネレーター式で any() を使用して、少なくとも 1 つの単語が大文字かどうかを確認します (.isupper())。結果を `has_uppercase` に代入します。 `has_uppercase` を評価します。
ヒントを表示
any(p.isupper() for 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 回の試行後に解決策が利用可能になります