---
title: 'Üreteç İfadeleri'
source: 'https://academia.sh/tr/kurslar/python-veri-yapilari/uretec-ifadeleri'
course: 'Veri Yapıları ve Fonksiyonel Araçlar'
language: tr
updated: '2026-08-17T18:10:26+00:00'
license: 'CC BY-SA 4.0'
---

# Üreteç İfadeleri

Bin öğelik toplamada üreteç de kavrama da 1000 nesne üretir ve ikisi de 499500 verir; ayrıldıkları tek yer listede tutulandır — 0'a karşı 1000. Tembel olan üretimi geciktirir, ondan kaçınmaz.

Önceki ders yalnız kurulum anını ölçtü ve orada uçurum vardı: kavrama daha ilk satırda
**1000** nesne var ediyor, üreteç **0** var ediyordu. Ama bir akış kurulup bırakılmak için
yazılmaz; er ya da geç tüketilir. Bin öğe gerçekten toplanacaksa üreteç de o bin nesneyi
üretmek zorundadır.

Bu dersin sorusu budur: aynı işi sonuna kadar götüren iki yazım, iş bittiğinde kaç nesne
üretmiş olur ve kaçını hâlâ elinde tutar? Yanıtın bir yarısı beklenen, öbür yarısı
beklenmedik çıkacak — ve tembelliğin gerçekte neyi azalttığı ancak orada görünecek. Ders
aynı zamanda üreteç ifadesinin kendi yazımını kurar: önceki derste tabloda bir satır olarak
duran biçim burada kendi başına ölçülür.

## Yazım

Üreteç ifadesi bir liste kavramasının köşeli ayraçlarının parantezle değiştirilmiş hâlidir
ve ürettiği şey bir liste değil, bir **üreteç nesnesidir**. Bir işleve tek argüman olarak
verildiğinde parantezler ayrıca yazılmaz; `sum(o.deger for o in akis)` yazımındaki ifade
kendi başına bir üreteç ifadesidir.

Ürettiği nesne önceki dersin üreteç işlevinin döndürdüğüyle aynı türdendir: yineleyicidir,
tek geçişliktir, `__iter__` kendisini döndürür. Fark yalnız yazımdadır. Üreteç işlevi ad
alır, birden çok deyim taşıyabilir, dallanabilir; üreteç ifadesi adsızdır ve tek bir
dönüşümü anlatır. Aralarındaki seçim maliyet değil, ifade genişliği seçimidir — ölçülen
sayılar ikisinde de aynıdır.

Programlama Temelleri kursu tembel değerlendirmeyi fonksiyonel programlamaya girişte bir
kavram olarak kurmuştu: değer, kullanıldığı ana kadar hesaplanmaz. Bu ders o kavramı
tekrarlamaz; onun Python'daki karşılığının **kaç nesneye mal olduğunu** sayar. Ve sayı,
kavramın adından beklenenden farklı çıkar.

Ölçümün varsayımları:

- **YN19** — Ortak tanımın `Oge` sınıfı ve `N = 1000` sayısı aynen kullanılır; sayma düzeni
  değiştirilmez. Kâhin kurgunun kendisidir.
- **YN20** — İki tüketim biçimi **aynı** sonucu hedefler: bin öğenin değer toplamı. Sonuç
  sütunu ölçümün doğruluk denetimidir; iki biçim ayrı sonuç verseydi karşılaştırma
  geçersiz olurdu.
- **YN21** — "Listede tutulan", toplama bittiğinde bir kapta canlı duran öğe sayısıdır;
  üreteçli biçimde böyle bir kap kurulmadığı için sıfırdır.
- **YN22** — Zincir ölçümünde üç halka vardır: üretme, süzme, dönüştürme. İki biçim aynı
  halkaları aynı sırada uygular; değişen tek şey her halkanın kap mı akış mı olduğudur.
- **YN23** — Zincirdeki "kaplarda tutulan" sayısı üç listenin uzunluklarının toplamıdır.
  **Bellek iddiası sayılan nesneyle kurulur, ölçülen baytla değil; süre ölçülmez.**
- **YN24** — Erken bırakma ölçümünde aranan koşul beşinci öğede sağlanır; koşulun yeri
  sabittir ve tüketicinin ne zaman durduğunu belirler.
- **YN25** — Tek geçişlilik ölçümü on öğelik küçük bir akışta yapılır; ölçülen şey büyüklük
  değil, ikinci toplamanın döndürdüğü değerdir.
- **YN26** — Kaynak değerlendirme ölçümünde `kaynak_ver` çağrılma sayısını kendi sayar; bu
  sayı, dış yinelenebilirin ne zaman değerlendirildiğinin ölçüsüdür.
- **YN27** — Son tabloda her işlem iki kap üzerinde ayrı ayrı denenir ve kurulum her
  denemede sıfırlanır; başarısız olan işlemin istisna sınıfı da koşumdan alınır. Yalnız
  standart kitaplık kullanılır.

## Ölçüm

```python
"""Uretec ifadesi: ayni sonuc, ayni uretim, baska tutma."""

import itertools

SAYAC = {"uretilen": 0}


class Oge:
    """Her uretimi sayan oge."""

    def __init__(self, deger):
        SAYAC["uretilen"] += 1
        self.deger = deger

    def __repr__(self):
        return f"Oge({self.deger})"


def sifirla():
    SAYAC["uretilen"] = 0


def uretilen():
    return SAYAC["uretilen"]


N = 1000


def uretec_tuketimi(n=N):
    sifirla()
    akis = (Oge(i) for i in range(n))
    toplam = sum(o.deger for o in akis)
    return uretilen(), toplam, 0


def kavrama_tuketimi(n=N):
    sifirla()
    liste = [Oge(i) for i in range(n)]
    toplam = sum(o.deger for o in liste)
    return uretilen(), toplam, len(liste)


print(f"{'tüketim biçimi':<22s} {'üretilen':>9s} {'toplam':>8s}"
      f" {'listede tutulan':>16s}")
for ad, f in (("üreteçle toplama", uretec_tuketimi),
              ("kavramayla toplama", kavrama_tuketimi)):
    u, t, tut = f()
    print(f"  {ad:<20s} {u:9d} {t:8d} {tut:16d}")


def zincir_tembel(n=N):
    sifirla()
    ciftler = (o for o in (Oge(i) for i in range(n)) if o.deger % 2 == 0)
    kareler = (o.deger * o.deger for o in ciftler)
    kurulumda = uretilen()
    toplam = sum(kareler)
    return kurulumda, uretilen(), toplam, 0


def zincir_liste(n=N):
    sifirla()
    hepsi = [Oge(i) for i in range(n)]
    ciftler = [o for o in hepsi if o.deger % 2 == 0]
    kareler = [o.deger * o.deger for o in ciftler]
    kurulumda = uretilen()
    toplam = sum(kareler)
    return kurulumda, uretilen(), toplam, len(hepsi) + len(ciftler) + len(kareler)


print()
print(f"{'zincir biçimi':<22s} {'kurulumda':>10s} {'üretilen':>9s}"
      f" {'toplam':>10s} {'kaplarda tutulan':>17s}")
for ad, f in (("üç üreteç ifadesi", zincir_tembel), ("üç liste kavraması", zincir_liste)):
    k, u, t, tut = f()
    print(f"  {ad:<20s} {k:10d} {u:9d} {t:10d} {tut:17d}")


def erken_birakma(n=N):
    sifirla()
    akis = (Oge(i) for i in range(n))
    bulundu = any(o.deger > 4 for o in akis)
    return uretilen(), bulundu


def erken_birakma_liste(n=N):
    sifirla()
    liste = [Oge(i) for i in range(n)]
    bulundu = any(o.deger > 4 for o in liste)
    return uretilen(), bulundu


print()
u1, b1 = erken_birakma()
u2, b2 = erken_birakma_liste()
print(f"tüketici beşinci öğede bıraktığında: üreteç ifadesi {u1} nesne üretti"
      f" (yanıt {b1}), liste kavraması {u2} (yanıt {b2})")

sifirla()
akis = (Oge(i) for i in range(10))
birinci = sum(o.deger for o in akis)
ikinci = sum(o.deger for o in akis)
print(f"aynı üreteç ifadesi iki kez toplandığında: {birinci} ve {ikinci},"
      f" üretilen {uretilen()}")

CAGRI = {"kaynak": 0}


def kaynak_ver():
    CAGRI["kaynak"] += 1
    return [1, 2, 3]


akis = (x for x in kaynak_ver())
kurulumda = CAGRI["kaynak"]
list(akis)
print(f"dış yinelenebilir kurulumda değerlendirildi mi: {kurulumda} çağrı,"
      f" gezildikten sonra {CAGRI['kaynak']}")

kalanlar = [5, 6, 7]
akis = (x * 10 for x in kalanlar)
kalanlar.append(8)
print(f"kaynağa sonradan eklenen öğe akışa girdi mi: {list(akis)}")

sifirla()
kume = {o.deger % 3 for o in (Oge(i) for i in range(9))}
print(f"küme kurucusuna verilen üreteç ifadesi: üretilen {uretilen()},"
      f" tutulan {len(kume)}")

ISLEMLER = (("len(n)", lambda n: len(n)),
            ("n[2]", lambda n: n[2].deger),
            ("n[:3]", lambda n: len(n[:3])),
            ("islice(n, 3)", lambda n: len(list(itertools.islice(n, 3)))))

print()
print(f"{'işlem':<14s} {'liste':>22s} {'üreteç ifadesi':>24s}")
for ad, islem in ISLEMLER:
    satir = []
    for kur in (lambda: [Oge(i) for i in range(N)],
                lambda: (Oge(i) for i in range(N))):
        sifirla()
        n = kur()
        try:
            sonuc = f"{islem(n)} ({uretilen()} üretim)"
        except TypeError as e:
            sonuc = f"{type(e).__name__} ({uretilen()} üretim)"
        satir.append(sonuc)
    print(f"  {ad:<12s} {satir[0]:>22s} {satir[1]:>24s}")

sifirla()
akis = (Oge(i) for i in range(N))
var_mi = any(o.deger == 2 for o in akis)
sinamada = uretilen()
kalan = sum(1 for _ in akis)
print()
print(f"akışta üyelik sınaması: yanıt {var_mi}, sınamada üretilen {sinamada},"
      f" akışta kalan {kalan}")
```

```
tüketim biçimi          üretilen   toplam  listede tutulan
  üreteçle toplama          1000   499500                0
  kavramayla toplama        1000   499500             1000

zincir biçimi           kurulumda  üretilen     toplam  kaplarda tutulan
  üç üreteç ifadesi             0      1000  166167000                 0
  üç liste kavraması         1000      1000  166167000              2000

tüketici beşinci öğede bıraktığında: üreteç ifadesi 6 nesne üretti (yanıt True), liste kavraması 1000 (yanıt True)
aynı üreteç ifadesi iki kez toplandığında: 45 ve 0, üretilen 10
dış yinelenebilir kurulumda değerlendirildi mi: 1 çağrı, gezildikten sonra 1
kaynağa sonradan eklenen öğe akışa girdi mi: [50, 60, 70, 80]
küme kurucusuna verilen üreteç ifadesi: üretilen 9, tutulan 3

işlem                           liste           üreteç ifadesi
  len(n)           1000 (1000 üretim)     TypeError (0 üretim)
  n[2]                2 (1000 üretim)     TypeError (0 üretim)
  n[:3]               3 (1000 üretim)     TypeError (0 üretim)
  islice(n, 3)        3 (1000 üretim)             3 (3 üretim)

akışta üyelik sınaması: yanıt True, sınamada üretilen 3, akışta kalan 997
```

## Aynı Üretim, Ayrı Tutma

Üst tablo ortak tanımın ikinci iddiasını tamamlıyor ve ilk sütun beklentiyi bozuyor.

**Üretilen sayı ikisinde de 1000.** Tembel olan biçim daha az nesne üretmiyor; bin öğe
istendi, bin öğe doğdu. Toplam sütunu da aynı: ikisi de **499500**. Yani iki yazım aynı işi
yapıyor, aynı sonucu veriyor ve aynı maliyeti ödüyor.

Ayrıldıkları tek sütun sonuncusudur. Toplama bittiğinde kavramayla yazılan biçimde **1000**
öğe hâlâ bir listede duruyor; üreteçle yazılan biçimde **0**. Üretilen bin nesnenin her biri
doğdu, toplamaya katkısını verdi ve ardından hiçbir kaba yazılmadığı için erişilemez oldu.
Kavramada ise hepsi listede kaldı, çünkü listenin işi tam olarak budur.

Buradan ortak tanımın cümlesi çıkar: **tembellik üretimi azaltmaz, tutmayı azaltır.** Bu,
"tembel değerlendirme" adının çağrıştırdığından daha dar bir iddiadır. Ad, işin
yapılmayacağını ima eder; ölçüm, işin yapıldığını ve yalnız **ne zaman** ile **sonrasında ne
kaldığı** sorularının değiştiğini gösterir. **Tembel olan üretimi geciktirir, ondan
kaçınmaz.**

Önceki dersin **0**'ı bu tabloyla birlikte okunmalıdır. Kurulumdaki sıfır bir tasarruf
vaadi değil, bir **erteleme** kaydıdır. Vaat tutulup tutulmadığı akışın nasıl tüketildiğine
bağlıdır, akışın nasıl yazıldığına değil.

## Zincirin Ara Kapları

Orta tablo tek bir dönüşümü değil, üç halkalı bir zinciri ölçüyor: üret, süz, dönüştür.
Toplam yine aynı — **166167000** — ve üretilen yine **1000**. İki sütun ayrılıyor.

Kurulum sütunu önceki dersin sonucunu tekrarlıyor: tembel zincir **0**, liste zinciri
**1000**. Ama asıl fark son sütundadır. Liste zinciri işini bitirdiğinde **2000** başvuru
kaplarda duruyor: bin öğelik kaynak listesi, beş yüz öğelik süzülmüş liste, beş yüz öğelik
dönüştürülmüş liste. Tembel zincirde bu sayı **0**.

Ara kapların sayısı zincirin uzunluğuyla büyür. Dört halkalı bir liste zinciri dört kap,
beş halkalı beş kap kurar; her halka kendinden öncekinin tamamını görmek ister ve gördüğünü
saklar. Tembel zincirde halka sayısı arttıkça kap sayısı artmaz, çünkü hiçbir halka
kendinden öncekinin tamamını istemez — her seferinde **bir** öğe ister.

Önceki dersin son satırıyla birlikte bu, zincirin kırılma noktasını verir: araya tek bir
`list()` çağrısı girdiğinde o noktada kap kurulur ve zincirin geri kalanının tembelliği o
kapı geri alamaz.

## Erken Bırakmanın Kaynağı

Bir sonraki satır, iddiaya yapılabilecek en doğal itirazı ölçüyor. Tüketici beşinci öğede
durduğunda üreteç ifadesi **6** nesne üretiyor, liste kavraması **1000**. Burada tembellik
gerçekten üretimden kaçınmış görünüyor.

Ayrım şurada: kaçınmayı sağlayan şey tembellik değil, **tüketicinin erken bırakmasıdır**.
`any` aradığını bulunca sormayı keser; tembel akış da sorulmayanı üretmez. Kavramada ise
tüketici erken bırakmış olsa bile üretim çoktan bitmiştir — liste, `any` daha ilk soruyu
sormadan doldurulmuştur.

İki durum birlikte iddianın tam biçimini verir: tembellik üretimi **tüketiciye bağlar**.
Tüketici her şeyi isterse her şey üretilir (birinci tablo: 1000); erken bırakırsa
üretilmeyen kalır (bu satır: 6). Kavramada üretim tüketiciden bağımsızdır ve her iki
durumda da **1000**'dir. Tembelliğin kazandırdığı, kaçınma değil, **kaçınma olanağıdır**.

Altıncı nesnenin neden üretildiği de aynı düzenin parçasıdır: koşul beşinci öğede sağlanır
ama `any` bunu ancak o öğeyi **aldıktan sonra** bilebilir, ve almak için bir üretim daha
gerekir.

## Kaynak Ne Zaman Değerlendirilir

Son dört satır üreteç ifadesinin iki ince yanını ölçüyor.

Birincisi tek geçişliliktir. Aynı üreteç ifadesi iki kez toplandığında **45** ve **0**
geliyor; üretilen **10**'da kalıyor. İkinci toplama boş bir akış üzerinde çalışıyor ve
`sum` boş akışta sıfır döndürüyor. Burada bir hata iletisi yoktur — sessiz bir sıfır
vardır. Bu, tek geçişliliğin en sinsi sonucudur: tükenmiş bir akış boş bir akıştan ayırt
edilemez.

İkincisi kaynağın ne zaman okunduğudur. `kaynak_ver` kurulum anında **bir kez** çağrılıyor
ve akış gezildikten sonra sayı yine **1**. Yani üreteç ifadesindeki en dıştaki
yinelenebilir **hemen** değerlendirilir; geciken şey öğelerin çekilmesidir, kaynağın
bulunmasıdır değil. Kaynak adı yanlışsa ya da çağrı hata veriyorsa, bu kurulumda ortaya
çıkar.

Bir sonraki satır bunun sınırını gösteriyor. Kaynak listesi kurulumda değerlendirildi ama
sonradan eklenen öğe akışa **girdi**: sonuç `[50, 60, 70, 80]`. Değerlendirilen şey liste
**nesnesiydi**, içeriğinin anlık kopyası değil. Önceki konunun görünüm ölçümüyle aynı
ayrımdır: bağ kurulmuştur, kopya alınmamıştır. Tembel bir akışın kaynağı akış tüketilmeden
önce değişirse, akış değişmiş hâli görür.

Son satır üreteç ifadesinin nereye verilebileceğini gösteriyor: küme kurucusuna verilen
akış **9** nesne ürettiriyor ve geriye **3** öğe tutuluyor. Var edilen ile tutulan
arasındaki fark burada da açık — kap ne kadarını saklayacağına kendisi karar veriyor.

## Akışın Yapamadıkları

Son tablo tutmamanın karşılığında nelerden vazgeçildiğini ölçüyor ve üç satırında aynı
istisna duruyor.

`len(n)` listede **1000** veriyor, akışta `TypeError`. Bir akış uzunluğunu bilmez, çünkü
bilmek için sonuna kadar gitmesi ve gittiğini hatırlaması gerekirdi. `n[2]` ve `n[:3]` de
aynı yanıtı veriyor: akış dizinlenemez ve dilimlenemez. Önceki konunun dilimleme dersinde
ölçülen her şey — dilimin yeni kap kurması, iç öğeleri paylaşması — bir akışta hiç
sorulamaz, çünkü dilim geriye dönüp bakmayı gerektirir ve akışın geriye bakacak bir yeri
yoktur.

Üç istisnanın da ortak gerekçesi budur: **sorulan her soru tutmayı gerektirir.** Uzunluk,
dizin ve dilim öğelerin bir arada durmasını varsayar; akış tam olarak bunu yapmayı
reddettiği için bu üç soruyu yanıtlayamaz. Sıfır tutmanın bedeli, üç yerleşik işlemin
kaybıdır.

Dördüncü satır kaybın telafi edilebildiği yeri gösteriyor. Standart kitaplığın `islice`
aracı ilk üç öğeyi akıştan alabiliyor ve akışta yalnız **3** üretim yaptırıyor; listede aynı
sonuç **1000** üretimden sonra geliyor. Dilim gibi görünen bir iş, geriye bakmadan
tanımlandığında akışta da yapılabilir hâle geliyor — ama sonuç bir dilim değil, yine bir
akıştır ve o da tek geçişliktir.

Son satır tek geçişliliğin en dikkat isteyen sonucudur. Akışta üyelik sınaması yanıtı
**True** veriyor ve sınamada yalnız **3** nesne üretiliyor; ama sınamadan sonra akışta
**997** öğe kalıyor. Sınama akışı **tüketti**: sorulan üç öğe geri gelmez. Aynı akış üzerinde
ikinci bir sınama yapılırsa üçüncü öğeden itibaren aranır ve baştaki üç öğe hiç
görülmez. Listede böyle bir yan etki yoktur; akışta sormak, okumaktır.

## Özet

- Bin öğelik toplamada üreteç de kavrama da **1000** nesne üretir ve ikisi de **499500**
  verir; ayrıldıkları tek yer listede tutulandır — **0**'a karşı **1000**. Tembel olan
  üretimi geciktirir, ondan kaçınmaz.
- Üç halkalı zincirde üretilen yine **1000**'dir ama liste biçimi bitişte **2000** başvuruyu
  kaplarda tutar, tembel biçim **0**. Ara kap sayısı zincir uzadıkça listede büyür,
  akışta büyümez.
- Tüketici beşinci öğede bıraktığında üreteç ifadesi **6**, kavrama **1000** üretir.
  Kaçınmayı sağlayan tembellik değil, tüketicinin durmasıdır; tembellik yalnız bunu
  **olanaklı** kılar.
- Üreteç ifadesi tek geçişliktir ve tükendiğinde sessizce boş davranır: ikinci toplama
  hata değil **0** verir.
- En dıştaki yinelenebilir kurulumda değerlendirilir (**1** çağrı), ama değerlendirilen şey
  nesnenin kendisidir: kaynağa sonradan eklenen öğe akışa girer.

## Sonraki Adım

Bu iki ders köşeli ayraç ile parantez arasındaki farkı ölçtü, ama köşeli ayracın kendisini
hiç açmadı. Oysa aynı yazım üç ayrı kap kurabilir — liste, küme ve sözlük — ve üçü aynı
kaynaktan aynı öğeleri alıp **farklı sayıda** öğe tutar. Üstelik yazım iç içe geçebilir ve
bir kavramanın içine bir kavrama daha girdiğinde ortaya kurulmamış bir kap çıkar. Sonraki
ders bunları sayar: üç kavrama biçimi aynı bin öğeden kaçını tutar, ve süzme koşulunun
nereye yazıldığı üretilen nesne sayısını değiştirir mi?
