🐍 class-666

📖 Ders 5 — Fonksiyonlar

Kendi komutunu icat et: def, parametre, return. Bitince 🟢 Kolay alıştırmalardan başla.

1. Neden fonksiyon? Kopyala-yapıştır cehennemi

Diyelim ki üç arkadaşını selamlayacaksın:

print("*" * 20)
print("Merhaba, ilker!")
print("*" * 20)

print("*" * 20)
print("Merhaba, ahmet!")
print("*" * 20)
# ... mehmet için bir daha kopyala 😩

Aynı kodu üç kez yazdın. Yarın çerçeveyi * yerine = yapmak istersen üç yeri düzelteceksin — birini unutursan program tutarsızlaşır. Fonksiyon bu derdi kökten çözer: tekrar eden işi bir kez tarif et, istediğin kadar kullan. Aslında yabancın da değil — print(), len(), type() hep birilerinin senin için yazdığı fonksiyonlardı. Bugün üretici tarafa geçiyorsun. 🏭

2. def: kendi komutunu icat et

def (define = tanımla), bir kod bloğuna isim takar. Tarif defterine yeni bir yemek eklemek gibi:

def selam_ver():          # tarifin adı: selam_ver
    print("Merhaba dünya!")   # tarifin adımları (girintili!)

Sözdizimi üç parçadır: def + isim + parantez () + iki nokta :. Gövde, tıpkı if ve for'daki gibi girintiyle içeride yazılır.

Tarif yazmak, yemeği pişirmek değildir! def bloğu çalıştırıldığında ekrana hiçbir şey gelmez — Python tarifi sadece deftere kaydeder. Kod ancak fonksiyon çağrılınca çalışır. "Fonksiyonu yazdım ama bir şey olmuyor" şikâyetinin sebebi %99 budur: çağırmayı unutmuşsundur.

3. Çağırmak: ismi + parantez

def selam_ver():
    print("Merhaba dünya!")

selam_ver()     # → Merhaba dünya!
selam_ver()     # → Merhaba dünya!
selam_ver()     # → Merhaba dünya!

Tarif bir kez yazıldı, yemek üç kez pişti. Kodun tek gerçek kuralı: önce tanımla, sonra çağır — Python yukarıdan aşağı okur, henüz tanımlanmamış fonksiyonu tanımaz.

Parantezi unutma! selam_ver (parantezsiz) fonksiyonu çalıştırmaz, sadece adından bahseder. print(selam_ver) dersen ekrana tuhaf bir <function selam_ver at 0x...> yazısı gelir. Çalıştıran şey parantezdir: selam_ver().

4. Parametre: makineye malzeme at

Yukarıdaki fonksiyon hep aynı şeyi söylüyor. Paranteze bir parametre koyarsan fonksiyon dışarıdan malzeme alan bir makineye dönüşür:

def bana_selam_ver(isim):        # isim = malzeme kapısı
    print(f"Merhaba, {isim}!")

bana_selam_ver("ilker")    # → Merhaba, ilker!
bana_selam_ver("ahmet")    # → Merhaba, ahmet!
bana_selam_ver("mehmet")   # → Merhaba, mehmet!

Çağrıda paranteze yazdığın değere argüman denir; içeride parametre adıyla yaşar. Birden fazla malzeme için virgülle sırala — çağrıdaki sıra, parametre sırasıyla eşleşir:

def dikdortgen_alan(en, boy):
    print(en * boy)

dikdortgen_alan(3, 5)    # en=3, boy=5 → 15
İsimlendirme sanattır: x, y yerine en, boy yazmak fonksiyonu okuyana (ve iki hafta sonraki sana) kendini anlattırır. Fonksiyon adları da fiil gibi iş anlatsın: selam_ver, alan_hesapla, cift_mi.

5. Varsayılan değer: "belirtilmezse böyle yap"

Parametreye = ile yedek değer verebilirsin. Argüman gelirse o kullanılır, gelmezse yedek devreye girer — restorandaki "acı belirtilmezse orta acı" kuralı:

def sayi_gir(sayi=0):
    print("Girilen sayı:", sayi)

sayi_gir(120)   # → Girilen sayı: 120
sayi_gir(11)    # → Girilen sayı: 11
sayi_gir()      # → Girilen sayı: 0   ← yedek devrede!

Zorunlu ve varsayılanlı parametreler karışabilir; varsayılanlılar sona yazılır: def kdvli_fiyat(fiyat, oran=20):

6. return: makineden çıkan ürün

⚡ Dersin en önemli kutusu: return ≠ print

print = camekana yazı asmak. Yoldan geçen okur ama eline bir şey geçmez.
return = müşterinin eline ürünü vermek. Değişkene koyar, üstünde hesap yaparsın.

def yaz(x):
    print(x * 2)      # ekrana yazar, ürün VERMEZ

def ver(x):
    return x * 2      # ürün verir, ekrana YAZMAZ

a = yaz(5)    # ekranda 10 belirir ama a = None 😱
b = ver(5)    # ekran boş ama b = 10 💪
print(b + 3)  # 13 — ürünle hesap yapabildim!

Ürün vermeyen fonksiyondan bir şey almaya çalışırsan eline Python'un "hiçlik" değeri None geçer. Sonucunu ileride kullanacağın her fonksiyonda return şart. Hem hesapla hem göster demek istiyorsan ikisini birleştir: print(ver(5)).

return'ün ikinci süper gücü: fonksiyonu o anda bitirir. Müfredattan asal kontrolü — bölen bulunduğu saniyede dava kapanır:

def asal_mi(sayi):
    if sayi < 2:
        return False        # 0 ve 1 asal değil — erken çıkış!
    for i in range(2, sayi):
        if sayi % i == 0:
            return False    # bölen bulundu, döngü bile devam etmez
    return True             # buraya ulaştıysa bölen yok → asal

print(asal_mi(17))   # True
print(asal_mi(25))   # False

7. Fonksiyondan fonksiyon çağırmak: LEGO 🧱

Bir fonksiyonun içinden başkasını çağırmak serbest — büyük programlar böyle kurulur: her parça tek iş yapar, karmaşık iş birleşimden doğar:

def kare(x):
    return x * x

def kareler_toplami(a, b):
    return kare(a) + kare(b)    # hesabı parçalara devret

print(kareler_toplami(3, 4))    # 9 + 16 = 25
Neden a*a + b*b yazmadık? Sonuç aynı olurdu ama kare() bir gün değişirse (örneğin sonucu yuvarlasın istersek) onu kullanan her fonksiyon bedavaya güncellenir. Tek yerde tanımla, her yerde kazan.

8. Kısa bakış: *args ve **kwargs

print(1, 2, 3, 4, 5)'in istediği kadar değer kabul etmesi dikkatini çekti mi? Sırrı yıldızlı parametreler. Şimdilik sadece tanışıyoruz — derinlemesine ilerideki konularda:

def kullanici_kayit(ad, soyad, **ek_bilgiler):
    print("Ad Soyad:", ad, soyad)
    print("Ekstralar:", ek_bilgiler)

kullanici_kayit("ilker", "turan", meslek="öğretmen", sehir="İstanbul")
# Ad Soyad: ilker turan
# Ekstralar: {'meslek': 'öğretmen', 'sehir': 'İstanbul'}

*args → sınırsız sıralı argümanı demet (tuple) olarak toplar. **kwargs → sınırsız isimli argümanı sözlük (dict) olarak toplar. "Kaç malzeme geleceği belli olmayan makine" gördüğünde aklına yıldızlar gelsin, bu kadarı yeter. ⭐

Son tuzak — kapsam (scope): fonksiyonun içinde tanımlanan değişkenler içeride yaşar, içeride ölür. def f(): sonuc = 5 yazıp dışarıda print(sonuc) dersen NameError alırsın. İçerideki değeri dışarı taşımanın resmi yolu zaten öğrendiğin şey: return.