Ana içeriğe geç
Modül 6 · Ders 3 ders 4Kurstaki 23/36~10 min
Modül dersleri (3/4)

Jeneratör ifadesi

üretici ifadesi bir liste kavrama gibidir, ancak köşeli parantezler yerine köşeli parantezler**. Fark dramatik: bellekte bir liste oluşturmaz, **talep üzerine** öğeler üretir, birer birer.

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

Tembellik (tembel değerlendirme)

Birisi bir sonraki değeri isteyene kadar jeneratör hiçbir şey yapmaz:

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

Tükenir: Tüm elementleri tükettikten sonra sonsuza kadar boştur. Yeniden kullanmak için yeniden oluşturmanız gerekir.

Ne zaman kullanılmalı?

Sonuçları sırayla tüketen bir işleve aktardığınızda:

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

sum, any, all, max, min, "".join(...) hepsi jeneratörleri kabul eder. Dış işlev yalnızca çağrı parantezlerini gerektiriyorsa, şunları yapabilirsiniz: jeneratörün kendisini hariç tutun:

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

any ve all: kısa devre

any(...) ve all(...) yanıtı alır almaz yinelemeyi bırakırlar. Bir jeneratörde aşağıdaki öğeler hesaplanmaz bile.

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)

Desen: tembel boru hattı

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

Çok büyük girdilerde bile ara liste yok.

Jeneratörleri toplam, herhangi biri, tümü ile tüketme

Oluşturucu ifadeleri, sum(), any() veya all() gibi yinelenebilirleri tüketen işlevlere doğrudan geçmek için mükemmeldir. Bu durumda, oluşturucu ifadesinin dış parantezlerini çıkararak şunu yazabilirsiniz:

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

Bu, kodunuzu temiz tutar ve bellek açısından yüksek verimlilik sağlar.

Deneyin

Egzersiz#python.m6.l3.e1
Denemeler: 0Yükleniyor…

sum() içindeki bir oluşturucu ifadesini kullanarak 1'den 100'e kadar (dahil) sayıların karelerinin toplamını hesaplayın. Bunu "toplam"a atayın. 'Toplam'ı değerlendirin.

Düzenleyici yükleniyor…
İpucu göster

range(1, 101) 100'ü içerir.

3 denemeden sonra çözüm mevcut

Alıştırmayı gözden geçirin

Egzersiz#python.m6.l3.e2
Denemeler: 0Yükleniyor…

`words = ['ciao', 'mondo', 'PYTHON', 'java']` verildiğinde, EN AZ bir kelimenin büyük harf (.isupper()) olup olmadığını kontrol etmek için bir jeneratör ifadesiyle any() kullanın. Sonucu "has_uppercase"e atayın. 'has_uppercase' değerini değerlendirin.

Düzenleyici yükleniyor…
İpucu göster

herhangi(p.isupper() kelimelerdeki p için)

3 denemeden sonra çözüm mevcut

Ek zorluk

Egzersiz#python.m6.l3.e3
Denemeler: 0Yükleniyor…

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.

Düzenleyici yükleniyor…
İpucu göster

Toplam_toplam = toplam(x**2, aralıktaki(1, 101) için) yazın. Çift parantezlere gerek yoktur.

3 denemeden sonra çözüm mevcut