← Kursa Dön
📄 Text · 15 min

if-elif-else Yapısı

Programlama dünyasında karar vermek her şeydir. Düşün: sabah kalktığında "hava yağmurlu mu?" diye sorarsın — cevaba göre şemsiye alırsın ya da almazsın. İşte Python'da if, elif ve else tam olarak bunu yapar. Programına "şu koşul sağlanıyorsa şunu yap, değilse bunu yap" deme gücü verir.

Bu ders, Python'daki koşullu ifadelerin tüm detaylarını kapsıyor. Basit if bloklarından başlayıp, match-case gibi modern yapılara kadar gideceğiz. Hazırsan, başlayalım!


if Nedir? Temel Söz Dizimi

if ifadesi, bir koşulun doğru (True) olup olmadığını kontrol eder. Koşul doğruysa altındaki kod bloğu çalışır, değilse atlanır. Bu kadar basit.

sicaklik = 35

if sicaklik > 30:
    print("Hava çok sıcak, bol su iç!")

Burada sicaklik > 30 bir boolean ifade — yani sonucu ya True ya da False. Değer 35 olduğu için koşul True döner ve print çalışır.

Söz dizimi kuralları çok net:

  • if anahtar kelimesi

  • Koşul ifadesi

  • İki nokta üst üste :

  • Alt satırda girintili (indented) kod bloğu

else: "Değilse" Durumu

Bazen sadece "koşul sağlanıyorsa yap" yetmez. "Sağlanmıyorsa da şunu yap" demek istersin. İşte else budur.

yas = 16

if yas >= 18:
    print("Ehliyet alabilirsin.")
else:
    print("Ehliyet için biraz daha beklemelisin.")

else bloğu, if koşulu False olduğunda çalışır. Dikkat et: else kendi başına bir koşul almaz. Sadece "yukarıdaki hiçbir koşul tutmadıysa" anlamına gelir.

Bir analoji yapayım: if-else yapısı bir yol ayrımına benzer. Yolun ikiye ayrıldığı noktadasın — ya sola gidersin ya sağa. Üçüncü bir seçenek yok (en azından şimdilik).

elif: Birden Fazla Koşul

Gerçek hayatta seçenekler genellikle ikiden fazladır. "Not 90'dan büyükse AA, 80'den büyükse BA, 70'den büyükse BB..." gibi. İşte elif (else if'in kısaltması) bu çoklu dallanmayı sağlar.

not_ortalamasi = 78

if not_ortalamasi >= 90:
    harf = "AA"
elif not_ortalamasi >= 80:
    harf = "BA"
elif not_ortalamasi >= 70:
    harf = "BB"
elif not_ortalamasi >= 60:
    harf = "CB"
else:
    harf = "FF"

print(f"Harf notun: {harf}")  # Harf notun: BB

Burada önemli bir detay var: Python koşulları yukarıdan aşağıya sırayla kontrol eder. İlk True olan koşulun bloğu çalışır ve geri kalanlar atlanır. Bu yüzden sıralama önemli!

Mesela not_ortalamasi 95 olsa, ilk koşul (>= 90) True olur, "AA" atanır ve alt satırlardaki elif'lere hiç bakılmaz. Bu bir kısa devre (short-circuit) davranışıdır.

elif Zinciri Ne Kadar Uzun Olabilir?

Teknik olarak sınır yok. Ama 5-6'dan fazla elif zinciri görüyorsan, muhtemelen bir dictionary mapping veya match-case kullanman daha temiz olur. Buna ileride değineceğiz.

# Uzun elif yerine dictionary yaklaşımı
gun_numarasi = 3

gunler = {
    1: "Pazartesi",
    2: "Salı",
    3: "Çarşamba",
    4: "Perşembe",
    5: "Cuma",
    6: "Cumartesi",
    7: "Pazar"
}

gun_adi = gunler.get(gun_numarasi, "Geçersiz gün")
print(gun_adi)  # Çarşamba

Indentation: Python'un Kalp Atışı

Python'da girintileme (indentation) sadece estetik değil, söz diziminin bir parçası. Diğer dillerde süslü parantezler {} blokları belirlerken, Python'da girintiler belirler.

# ✅ Doğru
if True:
    print("Bu çalışır")
    print("Bu da çalışır")

# ❌ Yanlış — IndentationError
if True:
print("Bu hata verir!")

Standart kural: 4 boşluk (space) kullan. Tab da çalışır ama tab ile space'i karıştırma — Python 3'te bu doğrudan TabError verir.

# ❌ Tab ve space karışımı — TabError!
if True:
    print("space ile")  # 4 space
	print("tab ile")    # 1 tab — HATA!

💡 İpucu: Modern editörlerin (VS Code, PyCharm) hepsi tab tuşuna bastığında otomatik 4 space ekler. Bu ayarı kontrol et ve "Insert Spaces" modunda olduğundan emin ol.

Bir blok içindeki tüm satırlar aynı seviyede girintili olmalı:

if True:
    print("satır 1")    # 4 space
    print("satır 2")    # 4 space
      print("satır 3")  # 6 space — IndentationError!

Nested if vs elif Zinciri

İç içe (nested) if blokları yazmak mümkün ama her zaman doğru seçim değil. Bakalım ne zaman hangisini kullanmalısın.

Nested if (İç İçe)

yas = 25
ehliyet_var = True

if yas >= 18:
    if ehliyet_var:
        print("Araba kullanabilirsin.")
    else:
        print("Önce ehliyet al.")
else:
    print("Yaşın yetmiyor.")

Burada ikinci if, birincinin içinde. Yani dıştaki koşul sağlanmadan içtekine bakılmaz bile. Bu mantıksal olarak doğru — yaşı yetmeyenin ehliyet durumunu kontrol etmenin anlamı yok.

Aynı Mantık, elif ile

yas = 25
ehliyet_var = True

if yas < 18:
    print("Yaşın yetmiyor.")
elif not ehliyet_var:
    print("Önce ehliyet al.")
else:
    print("Araba kullanabilirsin.")

Bu da aynı işi yapar ama daha düz (flat) bir yapıda. Genel kural: girintileme derinliği 2-3'ü geçiyorsa, yapıyı düzleştirmeyi düşün. Çünkü derin iç içe yapılar okunması zor "ok kodu" (arrow code) yaratır.

Arrow Code Problemi

# ❌ Arrow code — okunması zor
def islemi_yap(kullanici, siparis):
    if kullanici is not None:
        if kullanici.aktif:
            if siparis is not None:
                if siparis.toplam > 0:
                    if kullanici.bakiye >= siparis.toplam:
                        # Asıl iş burada
                        print("Sipariş onaylandı!")

Bu koda bak — asıl iş 5 seviye girintide! Bunu guard clause pattern ile düzeltebilirsin (birazdan göreceğiz).


Ternary Expression (Üçlü İfade)

Bazı if-else blokları o kadar basittir ki tek satırda yazılabilir. Python'un ternary (üçlü) ifadesi bunu sağlar.

n = 7

# Klasik yol
if n > 0:
    sonuc = "pozitif"
else:
    sonuc = "negatif"

# Ternary yol
sonuc = "pozitif" if n > 0 else "negatif"
print(sonuc)  # pozitif

Söz dizimi: değer_true if koşul else değer_false

Bu tek satırlık ifade, özellikle değişken ataması ve return ifadelerinde çok kullanışlı:

# Değişken ataması
durum = "yetişkin" if yas >= 18 else "çocuk"

# Return ifadesinde
def mutlak_deger(n):
    return n if n >= 0 else -n

# f-string içinde
print(f"Sayı {'çift' if n % 2 == 0 else 'tek'}")

İç İçe Ternary (Kaçının!)

Teknik olarak ternary'leri iç içe yazabilirsin ama yapma.

# ❌ Okunması zor
kategori = "A" if puan >= 90 else "B" if puan >= 70 else "C"

# ✅ Bunun yerine normal if-elif kullan
if puan >= 90:
    kategori = "A"
elif puan >= 70:
    kategori = "B"
else:
    kategori = "C"

⚠️ Dikkat: Ternary expression sadece basit, iki seçenekli durumlarda kullan. İç içe ternary yazmak kodun okunabilirliğini ciddi şekilde düşürür. "Akıllı kod" yazmak yerine "anlaşılır kod" yaz.


match-case: Python 3.10+ Structural Pattern Matching

Python 3.10 ile gelen match-case, diğer dillerdeki switch-case'e benzer ama çok daha güçlü. Sadece değer karşılaştırması değil, yapısal desen eşleştirmesi (structural pattern matching) yapabilir.

Temel Kullanım

komut = "start"

match komut:
    case "start":
        print("Sistem başlatılıyor...")
    case "stop":
        print("Sistem durduruluyor...")
    case "restart":
        print("Sistem yeniden başlatılıyor...")
    case _:
        print(f"Bilinmeyen komut: {komut}")

case _: burada wildcard — hiçbir desen tutmadığında çalışır. else'in karşılığı gibi düşün.

OR Pattern (Birden Fazla Değer)

gun = "cumartesi"

match gun:
    case "pazartesi" | "salı" | "çarşamba" | "perşembe" | "cuma":
        print("İş günü")
    case "cumartesi" | "pazar":
        print("Hafta sonu!")

| operatörü ile birden fazla deseni tek case'de birleştirebilirsin.

Yapısal Desen Eşleştirme

İşte match-case'in gerçek gücü buradan geliyor. Sadece değerleri değil, veri yapılarının şeklini eşleştirebilirsin.

# Tuple pattern matching
nokta = (3, 0)

match nokta:
    case (0, 0):
        print("Orijin noktası")
    case (x, 0):
        print(f"X ekseninde, x={x}")
    case (0, y):
        print(f"Y ekseninde, y={y}")
    case (x, y):
        print(f"Genel nokta: ({x}, {y})")

Burada x ve y değişkenleri otomatik olarak bağlanıyor (binding). (3, 0) değeri (x, 0) deseniyle eşleşir ve x otomatik olarak 3 olur. Bu, basit switch-case'in çok ötesinde bir özellik.

Guard (Koşullu Case)

yas = 25

match yas:
    case n if n < 0:
        print("Geçersiz yaş")
    case n if n < 18:
        print("Çocuk")
    case n if n < 65:
        print("Yetişkin")
    case _:
        print("Emekli")

if ile case'e ek koşul ekleyebilirsin. Buna guard denir.

Dict / Mapping Pattern

event = {"type": "click", "x": 100, "y": 200}

match event:
    case {"type": "click", "x": x, "y": y}:
        print(f"Tıklama: ({x}, {y})")
    case {"type": "keypress", "key": k}:
        print(f"Tuş basıldı: {k}")
    case _:
        print("Bilinmeyen event")

Dictionary'lerin yapısını eşleştirebilirsin — bu özellikle API response'ları veya event handling için harika.

💡 İpucu: match-case Python 3.10+ gerektirir. Eğer 3.9 veya altı kullanıyorsan, if-elif zinciri veya dictionary mapping kullanmaya devam et. Projenin minimum Python versiyonunu kontrol etmeyi unutma!


Truthy ve Falsy Değerler

Python'da her değer bir boolean bağlamında ya True (truthy) ya da False (falsy) olarak değerlendirilir. Bu, if ifadelerini çok daha kısa yazmana olanak tanır.

Falsy Değerler (False olarak değerlendirilen)

# Bunların hepsi False olarak değerlendirilir:
falsy_degerler = [
    False,      # Boolean False
    None,       # None
    0,          # Sıfır (int)
    0.0,        # Sıfır (float)
    0j,         # Sıfır (complex)
    "",          # Boş string
    [],         # Boş liste
    {},         # Boş dictionary
    set(),      # Boş set
    (),         # Boş tuple
    range(0),   # Boş range
]

for deger in falsy_degerler:
    print(f"{str(deger):12} -> bool: {bool(deger)}")

Bunlar dışındaki her şey truthy'dir. "False" string'i bile truthy'dir (boş olmayan string olduğu için)!

Kısa if Kalıpları

Bu bilgiyi kullanarak daha Pythonic kod yazabilirsin:

isimler = ["Ahmet", "Mehmet", "Ayşe"]

# ❌ Gereksiz uzun
if len(isimler) > 0:
    print("Liste dolu")

# ✅ Pythonic
if isimler:
    print("Liste dolu")

# ❌ Gereksiz uzun
if isim != "":
    print("İsim var")

# ✅ Pythonic
if isim:
    print("İsim var")

Aynı şekilde boşluk kontrolü:

sonuc = None

# ❌ Gereksiz uzun
if sonuc is not None:
    print(sonuc)

# ✅ Pythonic (çoğu durumda)
if sonuc:
    print(sonuc)

Ama Dikkatli Ol!

Truthy/falsy ile kısa if her zaman doğru değildir:

puan = 0

# ⚠️ Tehlikeli! 0 geçerli bir puan olabilir
if puan:  # 0 falsy olduğu için False döner
    print(f"Puan: {puan}")
else:
    print("Puan girilmemiş")  # Yanlış!

# ✅ Doğru yaklaşım
if puan is not None:
    print(f"Puan: {puan}")

0 geçerli bir değerse, if puan: kullanmak hatalı olur çünkü 0 falsy'dir. Bu durumda is not None kontrolü daha doğru.


Guard Clause Pattern (Erken Çıkış)

Guard clause, fonksiyonun başında geçersiz durumları eleyip erken çıkış (early return) yapma tekniğidir. Bu, iç içe if bloklarını düzleştirir ve kodun okunabilirliğini dramatik şekilde artırır.

Problemi Görelim

# ❌ Arrow code — derin iç içe yapı
def siparis_onayla(kullanici, urun, adet):
    if kullanici is not None:
        if kullanici.aktif:
            if urun is not None:
                if urun.stok >= adet:
                    if kullanici.bakiye >= urun.fiyat * adet:
                        # Asıl iş
                        kullanici.bakiye -= urun.fiyat * adet
                        urun.stok -= adet
                        return "Sipariş onaylandı!"
                    else:
                        return "Yetersiz bakiye"
                else:
                    return "Stok yetersiz"
            else:
                return "Ürün bulunamadı"
        else:
            return "Hesap aktif değil"
    else:
        return "Kullanıcı bulunamadı"

Bu kodu okumak gerçekten zor. else blokları hangi if'e ait, takip etmek kabus gibi.

Guard Clause ile Çözüm

# ✅ Guard clause — düz ve okunabilir
def siparis_onayla(kullanici, urun, adet):
    if kullanici is None:
        return "Kullanıcı bulunamadı"

    if not kullanici.aktif:
        return "Hesap aktif değil"

    if urun is None:
        return "Ürün bulunamadı"

    if urun.stok < adet:
        return "Stok yetersiz"

    if kullanici.bakiye < urun.fiyat * adet:
        return "Yetersiz bakiye"

    # Tüm kontroller geçti — asıl iş
    kullanici.bakiye -= urun.fiyat * adet
    urun.stok -= adet
    return "Sipariş onaylandı!"

Farkı gör: hiç iç içe yapı yok. Her kontrol bağımsız, sırayla yapılıyor. Bir koşul başarısız olursa fonksiyon hemen çıkıyor. Asıl iş mantığı en altta, hiç girintisiz.

Guard clause pattern'ının güzelliği, kapı görevlisi (bouncer) analojisiyle anlaşılır: Gece kulübünün kapısındaki görevli gibi düşün. Önce yaşını kontrol eder — uygun değilse geri çevirir. Sonra kıyafetini kontrol eder — uygun değilse geri çevirir. Her şey uygunsa içeri alır. Her kontrolde "geçemezsen git" mantığı var.

Guard Clause Ne Zaman Kullanılır?

  • Parametre doğrulama (validation): Fonksiyonun başında geçersiz girdileri ele

  • Hata durumları: Erken return ile hata mesajı döndürme

  • Ön koşullar: İşleme devam etmek için gereken minimum koşullar

def dosya_oku(dosya_yolu):
    if not dosya_yolu:
        return None

    if not dosya_yolu.endswith(".txt"):
        raise ValueError("Sadece .txt dosyaları desteklenir")

    # Guard'lar geçildi, asıl okuma işlemi
    with open(dosya_yolu, "r") as f:
        return f.read()

Karşılaştırma ve Mantıksal Operatörler

if ifadelerinde sıkça kullanılan operatörleri hızlıca hatırlayalım.

Karşılaştırma Operatörleri

a, b = 5, 10

print(a == b)   # False — eşit mi?
print(a != b)   # True  — eşit değil mi?
print(a > b)    # False — büyük mü?
print(a < b)    # True  — küçük mü?
print(a >= b)   # False — büyük eşit mi?
print(a <= b)   # True  — küçük eşit mi?

Mantıksal Operatörler: and, or, not

yas = 25
gelir = 5000

# and: İki koşul da True olmalı
if yas >= 18 and gelir >= 3000:
    print("Kredi başvurusu yapabilir")

# or: En az biri True olmalı
if yas < 18 or gelir < 1000:
    print("Kredi başvurusu reddedildi")

# not: Koşulu tersine çevirir
is_banned = False
if not is_banned:
    print("Giriş yapabilir")

Zincirleme Karşılaştırma (Chained Comparison)

Python'a özel güzel bir özellik:

yas = 25

# ❌ Diğer dillerdeki gibi
if yas >= 18 and yas <= 65:
    print("Çalışma yaşında")

# ✅ Python'a özel — matematik notasyonu gibi
if 18 <= yas <= 65:
    print("Çalışma yaşında")

# Birden fazla zincirleme
x = 5
if 0 < x < 10 < 100:  # 0 < 5 and 5 < 10 and 10 < 100
    print("Hepsi True")

Bu, matematikteki 18 ≤ yaş ≤ 65 notasyonunun birebir Python karşılığı. Çoğu dilde bu mümkün değil!

is vs ==

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a == b)   # True  — değerleri aynı
print(a is b)   # False — farklı nesneler
print(a is c)   # True  — aynı nesne

# None kontrolünde her zaman is kullan
x = None
if x is None:      # ✅ Doğru
    print("x None")
if x == None:      # ❌ Çalışır ama tavsiye edilmez
    print("x None")

== değer eşitliği, is kimlik eşitliği (aynı nesne mi?) kontrol eder. None, True, False kontrollerinde her zaman is kullan.

Short-Circuit Evaluation (Kısa Devre)

Python, mantıksal operatörlerde kısa devre değerlendirmesi yapar:

# and: İlk False'ta durur
def pahalı_fonksiyon():
    print("Çalıştım!")
    return True

# koşul1 False ise pahalı_fonksiyon hiç çağrılmaz
koşul1 = False
if koşul1 and pahalı_fonksiyon():
    print("İkisi de True")
# pahalı_fonksiyon çağrılmadı — performans kazancı!

# or: İlk True'da durur
koşul2 = True
if koşul2 or pahalı_fonksiyon():
    print("En az biri True")
# Yine pahalı_fonksiyon çağrılmadı

Bu davranış, guard clause pattern'ını güvenli yapar:

# items None olsa bile hata vermez
if items is not None and len(items) > 0:
    print(items[0])
# Çünkü items None ise, len(items) hiç çağrılmaz

Pratik Örnekler

Örnek 1: Basit Giriş Sistemi

kullanici_adi = "admin"
sifre = "12345"

girilen_kullanici = input("Kullanıcı adı: ")
girilen_sifre = input("Şifre: ")

if girilen_kullanici == kullanici_adi and girilen_sifre == sifre:
    print("Giriş başarılı! Hoş geldiniz.")
elif girilen_kullanici != kullanici_adi:
    print("Kullanıcı adı hatalı.")
else:
    print("Şifre hatalı.")

Örnek 2: Vergi Hesaplama (Dilim Sistemi)

gelir = 150000

if gelir <= 32000:
    vergi = gelir * 0.15
elif gelir <= 70000:
    vergi = 32000 * 0.15 + (gelir - 32000) * 0.20
elif gelir <= 170000:
    vergi = 32000 * 0.15 + 38000 * 0.20 + (gelir - 70000) * 0.27
elif gelir <= 880000:
    vergi = 32000 * 0.15 + 38000 * 0.20 + 100000 * 0.27 + (gelir - 170000) * 0.35
else:
    vergi = 32000 * 0.15 + 38000 * 0.20 + 100000 * 0.27 + 710000 * 0.35 + (gelir - 880000) * 0.40

print(f"Gelir: {gelir:,.0f} TL")
print(f"Vergi: {vergi:,.0f} TL")

Örnek 3: match-case ile Hesap Makinesi

sayi1 = float(input("Birinci sayı: "))
islem = input("İşlem (+, -, *, /): ")
sayi2 = float(input("İkinci sayı: "))

match islem:
    case "+":
        sonuc = sayi1 + sayi2
    case "-":
        sonuc = sayi1 - sayi2
    case "*":
        sonuc = sayi1 * sayi2
    case "/":
        if sayi2 == 0:
            print("Sıfıra bölme hatası!")
            sonuc = None
        else:
            sonuc = sayi1 / sayi2
    case _:
        print(f"Geçersiz işlem: {islem}")
        sonuc = None

if sonuc is not None:
    print(f"{sayi1} {islem} {sayi2} = {sonuc}")

Yaygın Hatalar ve Anti-Pattern'ler

1. Boolean ile Gereksiz Karşılaştırma

is_active = True

# ❌ Gereksiz
if is_active == True:
    print("Aktif")

# ✅ Pythonic
if is_active:
    print("Aktif")

# ❌ Gereksiz
if is_active == False:
    print("Pasif")

# ✅ Pythonic
if not is_active:
    print("Pasif")

2. Birden Fazla return Yerine Değişken Kullanma

# ❌ Gereksiz değişken
def kontrol(x):
    sonuc = False
    if x > 0:
        sonuc = True
    return sonuc

# ✅ Direkt return
def kontrol(x):
    return x > 0

3. Aynı Değişkeni Tekrar Tekrar Kontrol Etme

renk = "kırmızı"

# ❌ Tekrarlı
if renk == "kırmızı" or renk == "mavi" or renk == "yeşil":
    print("Geçerli renk")

# ✅ in operatörü ile
if renk in ("kırmızı", "mavi", "yeşil"):
    print("Geçerli renk")

4. Mutable Default ve if Kontrolü

# ❌ Tehlikeli
def ekle(item, liste=[]):
    liste.append(item)
    return liste

# ✅ Güvenli
def ekle(item, liste=None):
    if liste is None:
        liste = []
    liste.append(item)
    return liste

İleri Teknikler

Conditional Expression ile Dictionary

# Basit mapping'lerde dict kullan
STATUS_MESAJLARI = {
    200: "Başarılı",
    404: "Bulunamadı",
    500: "Sunucu Hatası",
}

kod = 404
mesaj = STATUS_MESAJLARI.get(kod, "Bilinmeyen durum kodu")
print(mesaj)  # Bulunamadı

any() ve all() ile Çoklu Koşul

notlar = [85, 72, 90, 68, 95]

# Herhangi biri 90'dan büyük mü?
if any(n > 90 for n in notlar):
    print("En az bir parlak öğrenci var!")

# Hepsi 60'tan büyük mü?
if all(n > 60 for n in notlar):
    print("Herkes geçti!")

Boolean Operatörlerin Dönüş Değeri

Python'da and ve or aslında True/False döndürmez — son değerlendirilen değeri döndürür:

# or: İlk truthy değeri döndürür
isim = "" or "Anonim"
print(isim)  # "Anonim"

# and: İlk falsy değeri veya son değeri döndürür
sonuc = "Ahmet" and "Mehmet"
print(sonuc)  # "Mehmet"

# Pratik kullanım: default değer atama
kullanici_ismi = girilen_isim or "Misafir"

Bu özellik default değer atama için çok kullanışlı, ama dikkatli ol — 0, "", [] gibi geçerli değerler de falsy'dir.


Özet

  • `if-elif-else` Python'un temel karar yapısıdır. Koşullar yukarıdan aşağıya sırayla kontrol edilir; ilk True olan çalışır.

  • Indentation Python'da söz diziminin parçasıdır — 4 space standart, tab/space karıştırma.

  • Ternary expression (x if koşul else y) basit if-else'leri tek satıra sığdırır, ama iç içe kullanma.

  • `match-case` (Python 3.10+) sadece değer değil yapısal desen eşleştirmesi yapar — tuple, dict, class pattern'ları destekler.

  • Truthy/falsy bilgisi ile daha kısa if ifadeleri yazabilirsin, ama 0 ve "" gibi geçerli falsy değerlere dikkat et.

  • Guard clause pattern ile derin iç içe yapıları düzleştir — fonksiyonun başında geçersiz durumları erken return ile ele.