---
title: 'Lambda ve Yüksek Mertebeden Fonksiyonlar'
source: 'https://academia.sh/tr/kurslar/python-veri-yapilari/lambda-ve-yuksek-mertebeden-fonksiyonlar'
course: 'Veri Yapıları ve Fonksiyonel Araçlar'
language: tr
updated: '2026-08-17T18:10:26+00:00'
license: 'CC BY-SA 4.0'
---

# Lambda ve Yüksek Mertebeden Fonksiyonlar

İşlev bir nesnedir ve argüman olarak geçirilebilir: iki yüz öğede anahtar işlevi sorted, min ve max için öğe başına tam bir kez çağrılır — aynı işi elle yazan sıralama onu 39800 kez çağırır.

Önceki derste süzme koşulu da öğe ifadesi de kavramanın içine gömülü kaldı. İkisi de bir
kural anlatıyordu — "şunu geçir", "şunu şuna dönüştür" — ama kural yazıldığı yerin dışında
kullanılamıyordu. Aynı süzgeci ikinci bir kavramada tekrarlamak, onu tekrar yazmak
demekti.

Kurallar adlandırılabilir. Bir işlev tam olarak budur: adlandırılmış bir kural. Bu dersin
sorusu, o işlevin bir **argüman** olarak geçirilip geçirilemeyeceği ve geçirildiğinde
**kaç kez çağrıldığıdır**. Sıralamada anahtar hesabı öğe başına bir kez mi yapılır, yoksa
her karşılaştırmada yeniden mi? Aradaki fark iki yüz öğede iki sayı üretecek ve ikisi aynı
büyüklükte olmayacak.

## İşlev Bir Nesnedir

Python'da `def` bir bildirim değil, bir **deyimdir**: çalıştığında bir işlev nesnesi üretir
ve onu bir ada bağlar. Bağlama başka her bağlama gibidir — nesne bir listeye konabilir, bir
sözlükte değer olabilir, bir işleve argüman olarak geçirilebilir, bir işlevden döndürülebilir.

`lambda` aynı nesneyi ad bağlamadan üretir. Tek bir ifade taşır, `return` yazılmaz, sonucu
ifadenin değeridir. Üretilen nesne `def` ile üretilenle **aynı türdendir**; ayrıldığı tek
yer taşıdığı addır.

Bir işlevi argüman olarak alan ya da işlev döndüren işleve **yüksek mertebeden fonksiyon
(higher-order function)** denir. Programlama Temelleri kursu bu kavramı fonksiyonel
programlamaya girişte kurdu; burada kavram tekrarlanmaz. Ölçülen şey Python'un yerleşik
yüksek mertebeden fonksiyonlarının verilen işlevi **kaç kez çağırdığı** ve **kaç nesne var
ettiğidir**.

## Anahtar İşlevinin Sözleşmesi

`sorted`, `min` ve `max` bir `key` argümanı kabul eder: her öğe için hesaplanacak
karşılaştırma değerini veren işlev. Sözleşmenin ölçülebilir yanı şudur — bu işlev öğe başına
**kaç kez** çağrılır?

İki yanıt akla gelir. Sıralama öğeleri birbiriyle karşılaştırır ve karşılaştırma sayısı öğe
sayısından fazladır; anahtar her karşılaştırmada hesaplanıyorsa çağrı sayısı da öyle olur.
Ya da anahtar bir kez hesaplanıp saklanır ve karşılaştırmalar saklanan değerler üzerinde
yapılır. İkinci yol çağrı sayısını düşürür ama **tutmayı** artırır: her öğe için bir anahtar
değeri canlı tutulmalıdır. Ölçüm hangisinin geçerli olduğunu söyler.

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

- **YN36** — Ortak tanımın `Oge` sınıfı sayma düzeniyle aynen kullanılır; `Oge` yalnız
  üretim sayar, anahtar çağrısı ayrı bir sayaçta tutulur.
- **YN37** — Anahtar işlevi her çağrılışını kendi sayar; "kaç kez çağrıldı" sorusunun ölçüsü
  bu sayaçtır ve kâhin kurgunun kendisidir.
- **YN38** — Kaynak **200** öğelidir ve dört işlemin dördü de aynı kaynak üzerinde çalışır.
  Sayaç her işlemden önce sıfırlanır.
- **YN39** — Anahtar değeri `-o.deger % 97` ile hesaplanır; sayı keyfîdir ve yalnız
  sıralamanın kaynak sırasından farklı bir sıra üretmesi için seçilmiştir.
- **YN40** — Elle yazılan seçmeli sıralama karşılaştırma başına anahtarı **iki kez**
  hesaplar; bu, anahtarı saklamayan bir yazımın davranışıdır ve ölçümün karşı ucudur.
  Sıralama bu derste bir algoritma olarak değil, **çağrı sayısı üreten bir kurgu** olarak
  kullanılır.
- **YN41** — `sorted` ile `liste.sort` ayrımı kimlikle ölçülür; **kimlik `is` ile
  gösterilir, sayısı basılmaz.**
- **YN42** — Eşleme ve süzme ölçümünde kurulum satırından hemen sonra sayaç okunur; öğe
  üreten işlev kasıtlı olarak yeni `Oge` üretir, böylece tembellik üretim üzerinden
  görünür.
- **YN43** — Üç işlevin ayrı nesneler olduğu ikişerli `is` karşılaştırmalarıyla gösterilir;
  kimlik sayısı basılmaz.
- **YN44** — Bağlama ölçümünde üç yazım da **aynı** üç işlevi kurar ve hepsi aynı öğeyle
  çağrılır; değişen tek şey çarpanın nereye yazıldığıdır.

## Ölçüm

```python
"""Islev bir nesnedir: anahtar islevi kac kez cagrilir, akis ne zaman var eder."""

import functools

SAYAC = {"uretilen": 0, "anahtar": 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
    SAYAC["anahtar"] = 0


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


def anahtar(o):
    """Ogenin siralama anahtari; her cagrilisini sayar."""
    SAYAC["anahtar"] += 1
    return -o.deger % 97


N = 200
KAYNAK = [Oge(i) for i in range(N)]


def elle_sec(ogeler, islev):
    """Her karsilastirmada anahtari yeniden hesaplayan secmeli siralama."""
    kalan, sirali = list(ogeler), []
    while kalan:
        enk = 0
        for i in range(1, len(kalan)):
            if islev(kalan[i]) < islev(kalan[enk]):
                enk = i
        sirali.append(kalan.pop(enk))
    return sirali


ISLEMLER = (("sorted(n, key=f)", lambda n: len(sorted(n, key=anahtar))),
            ("min(n, key=f)", lambda n: min(n, key=anahtar)),
            ("max(n, key=f)", lambda n: max(n, key=anahtar)),
            ("elle seçmeli sıralama", lambda n: len(elle_sec(n, anahtar))))

print(f"{'işlem':<24s} {'anahtar çağrısı':>16s} {'öğe başına':>11s}")
for ad, islem in ISLEMLER:
    sifirla()
    islem(KAYNAK)
    print(f"  {ad:<22s} {SAYAC['anahtar']:16d} {SAYAC['anahtar'] / N:11.1f}")

sifirla()
sirali = sorted(KAYNAK, key=anahtar)
print()
print(f"sorted(n) is n -> {sirali is KAYNAK}, var edilen {uretilen()},"
      f" paylaşılan {sum(1 for o in sirali if any(o is k for k in KAYNAK))}")
kopya = list(KAYNAK)
once = kopya
sonuc = kopya.sort(key=anahtar)
print(f"liste.sort dönen değer {sonuc!r}, kap aynı kaldı -> {once is kopya}")


def adli(o):
    return o.deger


adsiz = lambda o: o.deger
print()
print(f"{'işlev':<12s} {'çağrılabilir':>13s} {'__name__':>12s} {'tür aynı mı':>12s}")
for ad, f in (("def ile", adli), ("lambda ile", adsiz)):
    print(f"  {ad:<10s} {str(callable(f)):>13s} {f.__name__:>12s}"
          f" {str(type(f) is type(adli)):>12s}")

DEFTER = {"artir": lambda o: o.deger + 1, "iki_kat": lambda o: o.deger * 2}
print(f"sözlükte tutulan işlevler: {sorted(DEFTER)},"
      f" DEFTER['iki_kat'](Oge(21)) -> {DEFTER['iki_kat'](Oge(21))}")

sifirla()
esleme = map(lambda o: Oge(o.deger * 2), KAYNAK)
suzme = filter(lambda o: o.deger % 2 == 0, KAYNAK)
kurulumda = uretilen()
ilk = next(esleme)
print()
print(f"map ve filter kurulumda {kurulumda} nesne var etti,"
      f" ilk öğe istendiğinde {uretilen()}")
print(f"tümü gezildiğinde: map {len(list(esleme)) + 1} öğe,"
      f" filter {len(list(suzme))} öğe, üretilen {uretilen()}")

sifirla()
toplam = functools.reduce(lambda a, o: a + o.deger, KAYNAK, 0)
print(f"reduce ile toplam {toplam}, var edilen {uretilen()}")


def carpan_ureten(k):
    def carp(o):
        return o.deger * k
    return carp


uc = [carpan_ureten(k) for k in (1, 2, 3)]
ayri = all(a is not b for i, a in enumerate(uc) for b in uc[i + 1:])
print()
print(f"üç işlev birbirinden ayrı nesne -> {ayri},"
      f" sonuçlar {[f(Oge(10)) for f in uc]}")
print(f"carpan_ureten(2) is carpan_ureten(2) -> "
      f"{carpan_ureten(2) is carpan_ureten(2)}")

gec = [lambda o: o.deger * k for k in (1, 2, 3)]
erken = [lambda o, k=k: o.deger * k for k in (1, 2, 3)]
kismi = [functools.partial(lambda o, k: o.deger * k, k=k) for k in (1, 2, 3)]
print()
print(f"{'bağlama biçimi':<26s} {'nesne':>6s} {'sonuçlar':>16s}")
for ad, kap in (("gövdede serbest ad", gec), ("varsayılan argüman", erken),
                ("partial ile", kismi)):
    print(f"  {ad:<24s} {len(kap):6d} {str([f(Oge(10)) for f in kap]):>16s}")
```

```
işlem                     anahtar çağrısı  öğe başına
  sorted(n, key=f)                    200         1.0
  min(n, key=f)                       200         1.0
  max(n, key=f)                       200         1.0
  elle seçmeli sıralama             39800       199.0

sorted(n) is n -> False, var edilen 0, paylaşılan 200
liste.sort dönen değer None, kap aynı kaldı -> True

işlev         çağrılabilir     __name__  tür aynı mı
  def ile             True         adli         True
  lambda ile          True     <lambda>         True
sözlükte tutulan işlevler: ['artir', 'iki_kat'], DEFTER['iki_kat'](Oge(21)) -> 42

map ve filter kurulumda 0 nesne var etti, ilk öğe istendiğinde 1
tümü gezildiğinde: map 200 öğe, filter 100 öğe, üretilen 200
reduce ile toplam 19900, var edilen 0

üç işlev birbirinden ayrı nesne -> True, sonuçlar [10, 20, 30]
carpan_ureten(2) is carpan_ureten(2) -> False

bağlama biçimi              nesne         sonuçlar
  gövdede serbest ad            3     [30, 30, 30]
  varsayılan argüman            3     [10, 20, 30]
  partial ile                   3     [10, 20, 30]
```

## Öğe Başına Bir Çağrı

Üst tablonun ilk üç satırı aynı sayıyı veriyor: **200** çağrı, öğe başına **tam 1.0**.
Sıralama, en küçüğü bulma ve en büyüğü bulma — üçünde de anahtar işlevi her öğe için bir
kez çağrılıyor, daha fazla değil.

`min` ve `max` için bu beklenendir; her öğeye bir kez bakmak yeter. `sorted` için değildir.
Sıralama öğeleri birbiriyle karşılaştırmak zorundadır ve karşılaştırma sayısı öğe sayısından
fazladır. Yine de anahtar çağrısı **200**'de kalıyor: demek ki anahtarlar bir kez hesaplanıp
**saklanıyor** ve bütün karşılaştırmalar saklanan değerler üzerinde yapılıyor.

Dördüncü satır bu kararın karşı ucunu gösteriyor. Aynı işi yapan, anahtarı hiç saklamayan ve
her karşılaştırmada yeniden hesaplayan bir sıralama, aynı iki yüz öğede anahtarı **39800**
kez çağırıyor — öğe başına **199.0**. İki sayı arasındaki oran iki yüzdür ve bu oran öğe
sayısı büyüdükçe büyür.

Kursun ekseninden okunuşu şudur: yerleşik `sorted` bir **takas** yapıyor. Anahtar değerlerini
saklamak öğe sayısı kadar başvuru tutmak demektir; karşılığında çağrı sayısı öğe sayısına
iner. Tutmadan kaçınan yazım — dördüncü satır — hiçbir ara değer saklamıyor ve bedelini
çağrı sayısıyla ödüyor. Bu, ikinci dersin tersine çevrilmiş hâlidir: orada tutmayan biçim
kazanıyordu, burada tutan biçim kazanıyor. **Neyin tutulduğu kadar, tutmanın neyi ortadan
kaldırdığı da sayılmalıdır.**

Bu ölçüm bir sıralama algoritması karşılaştırması değildir; algoritmalar ve karmaşıklık
çözümlemesi Algoritmalar kursunun konusudur. Buradaki dördüncü satır yalnız anahtarı
saklamayan bir yazımın kaç çağrı ürettiğini göstermek için elle kuruldu.

## Yeni Kap mı, Yerinde mi

Sonraki iki satır aynı işin iki yazımını ayırıyor. `sorted` yeni bir liste üretiyor:
`sorted(n) is n` **yanlış**, var edilen `Oge` **0** ve paylaşılan **200**. Sıralama öğeleri
çoğaltmıyor, yalnız yeni bir kaba başka sırayla yazıyor — birinci dersin kap kurma ölçümünün
aynısı.

`liste.sort` yeni kap kurmuyor: kap aynı kalıyor ve dönen değer **`None`**. Bu, Python'da
yerinde çalışan yöntemlerin ortak imzasıdır ve bir sonucu vardır — `n = n.sort()` yazımı
listeyi `None` ile değiştirir. Ayrım tek satırda görünür: sonuç isteniyorsa `sorted`, kabı
korumak isteniyorsa `sort`.

## İşlevin Nesne Olduğunun Kanıtı

Orta tablo iki işlevi karşılaştırıyor ve üç sütunun ikisinde aynı yanıtı veriyor. `def` ile
tanımlanan ve `lambda` ile üretilen nesnelerin ikisi de **çağrılabilir**, ikisi de **aynı
türden**. Ayrıldıkları tek sütun `__name__`: biri kendi adını taşıyor, öbürü `<lambda>`.

Bu tek fark önemsiz görünür ama bir sonraki dersin ölçtüğü şeyin habercisidir. Bir işlev
nesnesi kendi adını bir öznitelikte taşır ve o öznitelik hata izlerinde, günlük kayıtlarında
ve belge üretiminde kullanılır. Adı olmayan bir nesne bu bilgiyi veremez.

Sonraki satır nesne olmanın pratikteki karşılığını gösteriyor: iki işlev bir sözlükte değer
olarak duruyor ve anahtarla çağrılıyor. Kural artık veriyle aynı yerde yaşıyor —
adlandırılabilir, saklanabilir, geçirilebilir. Önceki dersin kavramaya gömülü kalan süzgeci
burada bir sözlük değeri olabilirdi.

## Tembel Yüksek Mertebeden Yerleşikler

Son üç satır `map` ve `filter` yerleşiklerini ölçüyor ve tanıdık bir sayı çıkıyor: kurulumda
**0** nesne. İkisi de birer akış döndürüyor; verilen işlev kurulum anında hiç çağrılmıyor.
İlk öğe istendiğinde üretilen **1** oluyor, tümü gezildiğinde **200**.

Bu, üçüncü dersin iddiasının yerleşikler üzerindeki karşılığıdır: `map` üretimden kaçınmaz,
onu geciktirir. İki yüz öğe istendiğinde iki yüz nesne doğar. Süzme de aynı düzendedir ve
iki yüz öğeden **100**'ünü geçirir; geçmeyenler için yeni nesne kurulmadığı için üretim
sayısı yine iki yüzde kalır.

`map` ile bir kavrama arasındaki seçim bu yüzden bir maliyet seçimi değil, bir yazım
seçimidir — biri akış verir, öbürü kap. İkisinin sayıları önceki iki derste ölçüldü ve
burada değişmiyor.

Son satır üçüncü bir yüksek mertebeden aracı gösteriyor: standart kitaplığın `reduce`
işlevi, iki argümanlı bir işlevi akış boyunca uygulayarak tek bir değere iner. Toplam
**19900** ve var edilen **0** — hiçbir ara kap kurulmuyor, her adımda yalnız biriken değer
taşınıyor. Kavrama bir kap, `map` bir akış, `reduce` bir **değer** üretir; üçü de aynı
işlevi argüman olarak alır.

## İşlev Döndüren İşlev

Son iki blok yönü tersine çeviriyor: işlev artık argüman değil, **dönen değer**.

`carpan_ureten` çağrıldığında gövdesindeki `def` çalışır ve yeni bir işlev nesnesi üretir.
Üç çağrı **üç ayrı nesne** veriyor ve üçü ayrı sonuçlar üretiyor — her biri kendi çarpanını
taşıyor. Aynı argümanla yapılan iki çağrı bile ayrı nesne veriyor:
`carpan_ureten(2) is carpan_ureten(2)` **yanlış**. İşlev üretmek, her seferinde bir nesne
var etmektir; on ayrı çarpan on ayrı işlev nesnesi demektir.

Programlama Temelleri kursu kapanışı — iç işlevin dış kapsamdaki adı taşıması — bir kavram
olarak kurmuştu; burada eklenen tek şey o taşımanın **nesne sayısıyla** ölçülmesi ve
taşınanın bir **değer değil, bir ad** olmasıdır. Son tablo bu ayrımın sonucunu veriyor.

Üç yazım da üç işlev üretiyor ve üçünde de nesne sayısı **3**. Ama sonuçlar aynı değil.
**Gövdede serbest ad** kullanan biçim `[30, 30, 30]` veriyor: üç işlevin üçü de aynı `k`
adına bakıyor ve çağrıldıkları anda o adın son değeri **3**. Kapanış `k`'nin değerini
kopyalamadı, **adına bağlandı**.

**Varsayılan argüman** biçimi `[10, 20, 30]` veriyor. Python Temelleri kursunun fonksiyon
tanımı dersi varsayılan değerin **bir kez, tanım anında** değerlendirildiğini ölçmüştü;
orada bu bir tuzaktı, burada çözümdür. Değer tanım anında hesaplandığı için her işlev kendi
çarpanını yanında taşır. Standart kitaplığın `partial` aracı aynı sonucu argümanı önceden
bağlayarak verir.

Üç satır aynı yazımın üç okunuşudur ve aralarındaki fark ad ile değer arasındaki farktır.
Kavramada döngü adı kavrama bitince kaybolur; ona bağlanan işlev kaybolmaz ve son değeri
görür. **Bir ada bağlanmak, bir değeri almak değildir.**

## Özet

- `def` bir deyimdir ve bir işlev nesnesi üretir; `lambda` aynı türden nesneyi ad bağlamadan
  verir. İkisi de çağrılabilir, ikisi de aynı türdendir ve ayrıldıkları tek yer
  `__name__`'dir.
- İşlev nesnesi bir kapta değer olarak tutulabilir ve argüman olarak geçirilebilir; bir işlevi
  argüman alan ya da döndüren işlev yüksek mertebeden fonksiyondur.
- İki yüz öğede anahtar işlevi `sorted`, `min` ve `max` için **200** kez — öğe başına tam
  **bir** kez — çağrılır. Anahtarı saklamayan elle yazılmış sıralama aynı işlevi **39800**
  kez çağırır.
- `sorted` yeni kap kurar ve **200** öğeyi paylaşır, hiçbirini çoğaltmaz; `liste.sort`
  yerinde çalışır ve **`None`** döndürür.
- `map` ve `filter` kurulumda **0** nesne var eder, tümü gezildiğinde **200**; süzme iki
  yüz öğeden **100**'ünü geçirir. `reduce` ise hiç kap kurmadan tek değere iner.

## Sonraki Adım

Bu derste işlevler hep argüman olarak geçti; hiçbiri değiştirilmedi. Oysa bir işlev
döndürülebiliyorsa, bir işlevi alıp **yerine geçecek başka bir işlev** döndürmek de
mümkündür — özgün davranışı koruyup çevresine bir şeyler ekleyen bir sarmalayıcı. Sonraki
ders bu kalıbı ölçer: bir işlevi sarmalamak kaç nesne var eder, özgün nesneye ne olur, ve
sarmalanmış işlevin `__name__` özniteliği ne söyler? Bu dersin önemsiz görünen tek sütunu
orada bir sonuç üretecek.
