---
title: 'Fonksiyon Tanımı'
source: 'https://academia.sh/tr/kurslar/python-temelleri/fonksiyon-tanimi'
course: 'Python Temelleri'
language: tr
updated: '2026-08-17T18:10:29+00:00'
license: 'CC BY-SA 4.0'
---

# Fonksiyon Tanımı

Varsayılan değer her çağrıda değil, tanım okunduğunda bir kez değerlendirilir: beş çağrı bir tek değerlendirme yapar, değiştirilebilir bir varsayılan beş çağrıda beş öğe biriktirir ve altı parametrenin dördü tek bir yolla verilebilir.

Önceki ders döngünün bir protokol olduğunu ölçtü ve turların bitişine bir istisnanın karar
verdiğini gösterdi. Döngü gövdesi çoğu zaman bir işlev çağırır; her turda ona başka
değerler geçer.

Programlama Temelleri kursunun fonksiyon dersi parametre ile argüman ayrımını, dönüş
değerini ve çağrı çerçevesini kurmuştu; o ders **fonksiyonun ne olduğunu** anlatıyordu ve
argüman geçirmeyi tek bir soruya indirgemişti — hangi değer hangi parametreye gider.
Python'da bu sorunun yanıtı tek satırlık değildir: bir parametre yalnız konumundan, yalnız
adından ya da ikisinden de verilebilir; artan argümanlar toplanabilir; parametrelere
varsayılan değer bağlanabilir. Bunların içinde bir tanesi değer hakkında değil,
**zamanlama** hakkındadır ve bu dersin ölçtüğü şey odur: bir varsayılan değer **ne zaman**
hesaplanır — her çağrıda mı, yoksa bir kez mi?

## Varsayılan Bir İfadedir

`def` bir deyimdir ve çalıştırıldığında bir fonksiyon nesnesi üretir. Üretim sırasında
gövde çalıştırılmaz — o ders kurulmuştu — ama **imzadaki varsayılan değer ifadeleri
çalıştırılır**. Sonuçları hesaplanır ve fonksiyon nesnesinin üzerine yazılır.

Bunun anlamı şudur: varsayılan değer, çağrının değil **tanımın** parçasıdır. Çağrı
sırasında yeniden hesaplanmaz; tanım okunduğunda bir kez hesaplanmış olan nesne her
çağrıda yeniden **bağlanır**. Beş çağrı, beş ayrı varsayılan üretmez; beş kez aynı
nesneyi kullanır.

"Bir kez" ifadesi programın ömrü boyunca bir kez demek değildir; **tanım deyimi her
çalıştığında bir kez** demektir. En dış düzeydeki bir tanım dosya okunurken bir kez
çalışır, dolayısıyla varsayılanı da bir kez hesaplanır. Başka bir fonksiyonun gövdesine
yazılmış bir tanım ise **dış fonksiyonun her çağrısında** yeniden çalışır ve varsayılanını
o çağrıya özel olarak yeniden hesaplar. Ölçülen kural değişmiyor — varsayılan hâlâ
tanımın parçası — ama tanımın kaç kez çalıştığı değişiyor.

Değer değiştirilemez bir nesneyse bu ayrım görünmez. Bir sayının ya da bir dizginin her
çağrıda aynı nesne olması hiçbir sonuç doğurmaz, çünkü onu değiştirmenin yolu yoktur.
Ayrım, varsayılan **değiştirilebilir** olduğunda ortaya çıkar: gövde onu değiştirirse,
değişiklik bir sonraki çağrıya taşınır.

## Nöbetçi Değer

Bu davranışın karşısına konan kalıp, varsayılanı `None` yapıp gerçek değeri gövdede
üretmektir. `None` değiştirilemez, dolayısıyla paylaşılması bir sonuç doğurmaz; gövde her
çağrıda taze bir nesne kurar. Bu role **nöbetçi değer** denir: kendisi kullanılmaz, yalnız
"argüman verilmedi" bilgisini taşır.

Nöbetçinin `None` olması zorunlu değildir ama gerekçesi vardır. Bir parametrenin geçerli
değerleri arasında `None` da bulunabiliyorsa nöbetçi olarak `None` seçilemez — o zaman
"verilmedi" ile "`None` verildi" ayrılamaz. Bu durumda ayrı bir nesne nöbetçi yapılır.

## Bir Argüman Kaç Yolla Verilir

İkinci ölçü, argüman biçimlerinin sayısıdır. Python imzada iki ayraç tanır. Eğik çizgi,
solundaki parametrelerin **yalnız konumsal argümanla** verilebileceğini bildirir. Yıldız,
sağındaki parametrelerin **yalnız anahtarlı argümanla** verilebileceğini bildirir. İkisinin
arasında kalanlar her iki yolla da verilebilir.

Buna iki toplayıcı eklenir. Yıldızlı bir parametre, karşılanmamış **konumsal** argümanları
bir demette toplar; çift yıldızlı bir parametre, karşılanmamış **anahtarlı** argümanları
bir sözlükte toplar. İkisine birlikte **değişken sayıda argüman** denir ve imzanın kaç
argüman alabileceğini üst sınırdan kurtarır.

İmzadaki bu parçaların sırası serbest değildir: önce yalnız konumsal olanlar, sonra her
iki yolla verilebilenler, sonra konumsal toplayıcı, sonra yalnız anahtarlı olanlar, en
sonda anahtarlı toplayıcı gelir. Sıra, bağlanmayı **tek anlamlı** kılmak için vardır.
Çağrıdaki argümanlar soldan sağa okunur; konumsal olanlar imzadaki konumsal parametreleri
sırayla doldurur, dolduramadıkları toplayıcıya girer, anahtarlı olanlar adlarıyla
eşleşir, eşleşemeyenler anahtarlı toplayıcıya düşer. Bu sıra bozulsaydı aynı çağrının
birden çok geçerli bağlanması olurdu ve hangisinin seçileceği yazılana bakılarak
söylenemezdi.

Aynı gerekçe varsayılan taşıyan parametrelerin taşımayanlardan sonra gelmesini de
zorunlu kılar — konumsal tarafta. Yalnız anahtarlı tarafta bu kısıt yoktur: orada
eşleşme ada göre yapıldığı için varsayılanı olan ve olmayan parametreler karışık
sırayla yazılabilir.

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

- **PA16** — Kâhin kurgunun kendisidir: varsayılan ifadesi bir işlev çağrısıdır ve her
  değerlendirilişini kaydeder; "kaç kez değerlendirildi" sorusunun ölçüsü bu kayıttır.
- **PA17** — Değerlendirme sayısı iki noktada okunur: tanım deyimi çalıştıktan hemen
  sonra ve beş çağrı yapıldıktan sonra. İkisinin farkı, çağrıların kattığı
  değerlendirmedir.
- **PA18** — İki fonksiyon aynı işi yapar ve yalnız varsayılanında ayrılır: biri boş bir
  liste, öbürü `None` nöbetçisi. Gövdelerin geri kalanı birebir aynıdır.
- **PA19** — Paylaşım, art arda iki çağrının döndürdüğü nesne `is` ile karşılaştırılarak
  gösterilir; **hiçbir kimlik sayısı basılmaz**. Karşılaştırılan nesne bir listedir;
  değiştirilemez küçük değerlerin önbelleklenmesi ölçüme karışmaz.
- **PA20** — İmza altı parametre ve iki toplayıcı taşır; sayılar bu imzaya özgüdür ve
  başka bir imzaya taşınmaz.
- **PA21** — Bağlanamayan çağrılarda yalnız **istisnanın sınıfı** yazılır, iletisi
  yazılmaz; ileti metni ölçünün parçası değildir.
- **PA22** — Varsayılanın nerede durduğu, fonksiyon nesnesinin varsayılanları taşıyan
  alanı okunarak gösterilir; okunan şey bir bellek bilgisi değil, dilin kendi tanımladığı
  bir alandır.
- **PA23** — Çağrı yerindeki açma biçimi, imzadaki toplayıcılarla aynı ayraçları kullanır
  ama ters yönde çalışır; ölçümde ikisi aynı imza üzerinde karşılaştırılır.

## Ölçüm

```python
"""Varsayilan deger ne zaman degerlendirilir ve argumanlar nasil baglanir."""

DEGERLENDIRME = []


def damga(ad):
    """Her cagrildiginda kaydeder; varsayilan ifadesi olarak kullanilir."""
    DEGERLENDIRME.append(ad)
    return len(DEGERLENDIRME)


def sirala(x, d=damga("varsayılan ifade")):
    return d


print(f"tanımdan hemen sonra değerlendirme: {len(DEGERLENDIRME)}")
sonuclar = [sirala(i) for i in range(5)]
print(f"beş çağrıdan sonra değerlendirme: {len(DEGERLENDIRME)}")
print(f"beş çağrının döndürdüğü: {sonuclar}")


def biriktir(x, kova=[]):
    kova.append(x)
    return kova


def nobetci(x, kova=None):
    if kova is None:
        kova = []
    kova.append(x)
    return kova


print()
print(f"{'çağrı':>6s} {'kova=[] uzunluk':>16s} {'kova=None uzunluk':>18s}")
onceki_a = onceki_b = None
for i in range(1, 6):
    a, b = biriktir(i), nobetci(i)
    print(f"  {i:4d} {len(a):16d} {len(b):18d}")
    if i > 1:
        ayni_a, ayni_b = a is onceki_a, b is onceki_b
    onceki_a, onceki_b = a, b
print(f"art arda iki çağrının kovası aynı nesne mi: "
      f"kova=[] {ayni_a}, kova=None {ayni_b}")
print(f"fonksiyon nesnesinde duran varsayılan: "
      f"biriktir {biriktir.__defaults__}, nobetci {nobetci.__defaults__}")
print(f"dönen liste, fonksiyonda duran varsayılanın kendisi mi: "
      f"{biriktir(6) is biriktir.__defaults__[0]}")


def kaydol(a, b, /, c, d=40, *ek, e, f=60, **kalan):
    """a,b yalnız konumsal; e,f yalnız anahtarlı; ek ve kalan artanı toplar."""
    return {"a": a, "b": b, "c": c, "d": d, "ek": ek, "e": e, "f": f,
            "kalan": kalan}


CAGRILAR = (
    "kaydol(1, 2, 3, e=5)",
    "kaydol(1, 2, c=3, e=5)",
    "kaydol(1, 2, 3, 4, 7, 8, e=5, f=9, g=0)",
    "kaydol(1, 2, 3)",
    "kaydol(a=1, b=2, c=3, e=5)",
)

print()
print(f"{'çağrı':<42s} bağlanma")
for metin in CAGRILAR:
    try:
        s = eval(metin)
        b = (f"a={s['a']} b={s['b']} c={s['c']} d={s['d']} ek={s['ek']} "
             f"e={s['e']} f={s['f']} kalan={s['kalan']}")
    except TypeError as hata:
        b = type(hata).__name__
    print(f"  {metin:<40s} {b}")

KONUMSAL = (1, 2, 3)
ANAHTARLI = {"e": 5, "g": 0}
acilan = kaydol(*KONUMSAL, **ANAHTARLI)
print(f"  {'kaydol(*KONUMSAL, **ANAHTARLI)':<40s} "
      f"a={acilan['a']} b={acilan['b']} c={acilan['c']} d={acilan['d']} "
      f"ek={acilan['ek']} e={acilan['e']} f={acilan['f']} "
      f"kalan={acilan['kalan']}")

print()
print("parametre  konumsal verilebilir  anahtarlı verilebilir")
for ad, konumsal, anahtarli in (("a", True, False), ("b", True, False),
                                ("c", True, True), ("d", True, True),
                                ("e", False, True), ("f", False, True)):
    print(f"  {ad:<8s} {('evet' if konumsal else 'hayır'):>18s}"
          f" {('evet' if anahtarli else 'hayır'):>21s}")
```

```
tanımdan hemen sonra değerlendirme: 1
beş çağrıdan sonra değerlendirme: 1
beş çağrının döndürdüğü: [1, 1, 1, 1, 1]

 çağrı  kova=[] uzunluk  kova=None uzunluk
     1                1                  1
     2                2                  1
     3                3                  1
     4                4                  1
     5                5                  1
art arda iki çağrının kovası aynı nesne mi: kova=[] True, kova=None False
fonksiyon nesnesinde duran varsayılan: biriktir ([1, 2, 3, 4, 5],), nobetci (None,)
dönen liste, fonksiyonda duran varsayılanın kendisi mi: True

çağrı                                      bağlanma
  kaydol(1, 2, 3, e=5)                     a=1 b=2 c=3 d=40 ek=() e=5 f=60 kalan={}
  kaydol(1, 2, c=3, e=5)                   a=1 b=2 c=3 d=40 ek=() e=5 f=60 kalan={}
  kaydol(1, 2, 3, 4, 7, 8, e=5, f=9, g=0)  a=1 b=2 c=3 d=4 ek=(7, 8) e=5 f=9 kalan={'g': 0}
  kaydol(1, 2, 3)                          TypeError
  kaydol(a=1, b=2, c=3, e=5)               TypeError
  kaydol(*KONUMSAL, **ANAHTARLI)           a=1 b=2 c=3 d=40 ek=() e=5 f=60 kalan={'g': 0}

parametre  konumsal verilebilir  anahtarlı verilebilir
  a                      evet                 hayır
  b                      evet                 hayır
  c                      evet                  evet
  d                      evet                  evet
  e                     hayır                  evet
  f                     hayır                  evet
```

## Bir Kez Değerlendirilen İfade

İlk üç satır zamanlama sorusunu kapatıyor. Tanım deyimi çalıştıktan hemen sonra, **henüz
hiçbir çağrı yapılmadan**, değerlendirme sayısı **1**. Varsayılan ifadesi tanım okunurken
çalışmış.

Beş çağrıdan sonra sayı yine **1**. Çağrılar hiçbir değerlendirme eklemedi. Üçüncü satır
bunu doğrudan gösteriyor: beş çağrının beşi de aynı değeri döndürüyor — hepsi tanım
sırasında hesaplanmış tek nesneyi görüyor.

Bir fonksiyonun çağrılma sayısı ile varsayılanının değerlendirilme sayısı arasında
**bağlantı yoktur**. Bu, imzada yazılan ifadenin gövdede yazılmış gibi okunmasının neden
yanlış olduğunu açıklar. `def` satırındaki bir ifade, gövdedeki bir ifadeyle aynı yerde
durmuyor: biri bir kez, öbürü her çağrıda çalışıyor.

## Paylaşılan Kova

Orta tablo bu tek değerlendirmenin bedelini ödetiyor. Sol sütunda varsayılan boş bir
liste; beş çağrı boyunca uzunluk **1, 2, 3, 4, 5** diye büyüyor. Her çağrı bir öncekinin
bıraktığı listeyi buluyor.

Sağ sütunda nöbetçi kalıbı; uzunluk beş çağrıda da **1**. Her çağrı kendi listesini
kuruyor ve bir öncekinden hiçbir şey devralmıyor.

Alt satır nedeni kimlik üzerinden söylüyor. `kova=[]` biçiminde art arda iki çağrının
döndürdüğü nesne `is` sınamasından **doğru** çıkıyor: aynı nesne. Nöbetçi kalıbında
**yanlış**: ayrı nesneler. Fonksiyonun her çağrıda "yeni bir liste" aldığı sanısı burada
kırılıyor — liste tanım sırasında bir kez kurulmuş, fonksiyon nesnesine bağlanmış ve o
tarihten sonra her çağrının değiştirdiği tek bir nesne olarak yaşıyor.

Sondan bir önceki satır varsayılanın **nerede durduğunu** gösteriyor ve bu, dersin en
doğrudan kanıtıdır. Fonksiyon nesnesinin varsayılanları taşıyan alanı okunduğunda içinde
`[1, 2, 3, 4, 5]` duruyor — beş çağrının biriktirdiği liste, çağrılar bittikten sonra
**fonksiyonun kendisinde**. Nöbetçi kalıbında aynı alanda yalnız `None` var; orada
biriken hiçbir şey yok, çünkü biriken listeler gövdede kurulup çağrıyla birlikte
bırakıldı.

Son satır halkayı kapatıyor: bir çağrının döndürdüğü liste ile fonksiyon nesnesinde duran
varsayılan `is` sınamasından **doğru** çıkıyor. İkisi tek bir nesne. "Varsayılan tanımın
parçasıdır" cümlesi burada bir yorum olmaktan çıkıyor; fonksiyonun üzerinde durduğu
okunabiliyor.

Sonucun kendisi bir hata değil, kuralın doğrudan sonucudur. Programlama Temelleri kursu
bu tuzağı bir uyarı olarak yazmıştı; buradaki sayılar uyarının gerekçesini veriyor.
Kuralı bilen için davranış şaşırtıcı değildir: gövde varsayılanı değiştiriyorsa,
değiştirdiği şey **tanımın parçasıdır**.

## Altı Parametre, İki Ayraç

Alt iki tablo bağlanmayı ölçüyor. İlk iki çağrı aynı sonucu veriyor: `c` bir kez konumdan,
bir kez adından veriliyor ve bağlanma birebir aynı. `d`, `e` ve `f` verilmediği için `d`
ile `f` varsayılanlarına düşüyor, `e` ise çağrıda mutlaka yazılmak zorunda — çünkü
varsayılanı yok ve yalnız anahtarlı verilebiliyor.

Üçüncü çağrı iki toplayıcıyı da dolduruyor. Altı konumsal argüman veriliyor; ilk dördü
`a`, `b`, `c`, `d` parametrelerini karşılıyor, artan **iki tanesi** `ek` demetine
giriyor. Anahtarlı tarafta `e` ile `f` kendi parametrelerini buluyor, imzada karşılığı
olmayan `g` ise `kalan` sözlüğüne düşüyor. Toplayıcılar, bağlanamayan argümanı hataya
dönüştürmek yerine **toplayan** parametrelerdir.

Son iki çağrı bağlanamıyor ve ikisi de `TypeError` veriyor. Dördüncü çağrıda `e` eksik:
varsayılanı olmayan, yalnız anahtarlı bir parametre yazılmadan çağrı kurulamaz. Beşinci
çağrıda tam tersi olmuş — `a` ile `b` adlarıyla verilmiş, oysa eğik çizginin solundalar ve
yalnız konumdan alınabilirler. Adlarıyla verilen `a` ile `b`, parametreleri karşılamak
yerine `kalan` sözlüğüne düşecek adlar olarak görülüyor ve iki konumsal parametre boş
kalıyor.

Altıncı satır aynı ayraçların **çağrı yerinde** ne yaptığını gösteriyor. İmzada yıldız
argümanları **toplarken**, çağrıda tam tersini yapar: bir demeti konumsal argümanlara,
bir sözlüğü anahtarlı argümanlara **açar**. Üç öğelik demet `a`, `b`, `c` parametrelerini
karşılıyor; sözlükteki `e` kendi parametresini buluyor, `g` ise `kalan` sözlüğüne düşüyor.

İki yönün aynı ayraçları kullanması bir rastlantı değil: toplama ile açma birbirinin
tersidir ve bir fonksiyonun aldığı argümanları başka bir fonksiyona olduğu gibi
geçirmenin yolu ikisini yan yana kullanmaktır. Bu, sarmalayan fonksiyon yazmanın temel
kalıbıdır — sarmalayan, imzayı bilmeden argümanları toplar ve sarmaladığı fonksiyona açar.

Son tablo imzanın tümünü özetliyor. Altı parametrenin **dördü tek bir yolla** verilebilir
— `a` ile `b` yalnız konumdan, `e` ile `f` yalnız addan. Yalnız **ikisi** her iki yolu da
kabul ediyor. Ayraçların işi budur: bir parametrenin kaç yolla verilebileceğini daraltmak.
Daraltmanın karşılığı, çağrı yazımının imzayla birlikte değişmemesidir — konumsal
tutulan bir parametrenin adı değiştiğinde hiçbir çağrı bozulmaz, anahtarlı tutulan bir
parametrenin sırası değiştiğinde de öyle.

## Özet

- Varsayılan değer ifadesi çağrının değil **tanımın** parçasıdır: tanım okunurken bir kez
  değerlendirilir ve beş çağrı bu sayıyı değiştirmez — çağrı sayısıyla değerlendirme
  sayısı arasında bağlantı yoktur.
- Değiştirilemez bir varsayılanda bu görünmez; **değiştirilebilir** bir varsayılanda gövde
  tanımın parçasını değiştirir ve beş çağrı tek bir listede **beş öğe** biriktirir.
- `None` nöbetçisi kalıbı taze nesneyi gövdede kurar; art arda iki çağrının kovası `is`
  sınamasından ayrı nesneler olarak çıkar ve uzunluk her çağrıda **1** kalır.
- Eğik çizgi solundaki parametreleri yalnız konumsal, yıldız sağındakileri yalnız
  anahtarlı yapar; ölçülen imzada altı parametrenin **dördü tek yolla**, ikisi iki yolla
  verilebilir.
- Yıldızlı ve çift yıldızlı toplayıcılar karşılanmamış konumsal ve anahtarlı argümanları
  toplar; aynı ayraçlar çağrı yerinde ters yönde çalışır ve bir demetle bir sözlüğü
  argümanlara **açar**. Toplanamayan argüman ile eksik kalan parametre `TypeError` üretir.
- Varsayılan, fonksiyon nesnesinin kendi alanında durur: beş çağrıdan sonra o alanda
  biriken listenin tamamı okunabilir ve dönen liste `is` sınamasıyla onunla aynı nesne
  çıkar.

## Sonraki Adım

Fonksiyon gövdesi, argümanlarla gelen adların yanında başka adlar da kullanır: gövdede
kurulanlar, onu çevreleyen tanımdan gelenler, dosyanın en dışında duranlar ve dilin kendi
sağladıkları. Programlama Temelleri kursu bu arama sırasını dilden bağımsız bir kavram
olarak kurmuştu. Python'da sıra **dört düzeylidir** ve düzeylerden hangisinde bulunacağını
belirleyen şey adın nerede **okunduğu** değil, nerede **atandığıdır**. Sonraki ders aynı
adı dört düzeyde birden tanımlayıp hangisinin kazandığını ölçer — ve gövdeye tek bir atama
satırı eklemenin aynı adı nasıl başka bir düzeye taşıdığını.
