Python ile Programlama · Ünite 3
Kontrol Yapıları: if, Döngüler, break–continue ve Hata Ayıklama
10 soruluk deneme testine geç ↓1. Koşullu ifadeler: if, elif, else
Program yalnızca veri saklamaz, duruma göre karar verir: bakiye yeterli mi, kullanıcı giriş yapmış mı? Koşullu ifade, bir koşulun sağlanıp sağlanmadığına bakarak hangi kod bloğunun çalışacağını seçen yapıdır. Söz dizimi üç parçadır: anahtar sözcük, koşul ve sonda iki nokta üst üste (:); ardından girintili gövde gelir.
sicaklik = 32
if sicaklik > 30:
print("Hava çok sıcak.") # girintili: koşula bağlı
print("Su içmeyi unutma.")
print("Program bitti.") # girintisiz: her durumda çalışırelif zinciri ve sıralama
İkiden fazla seçenek için elif (else if) kullanılır; sayısının sınırı yoktur. Python koşulları yukarıdan aşağı dener, ilk doğru koşulu çalıştırır ve zincirin geri kalanına hiç bakmaz. else bütün koşullar yanlışsa çalışan isteğe bağlı son daldır.
puan = 82
if puan >= 90:
harf = "AA"
elif puan >= 80:
harf = "BB" # 82 burada yakalanır, aşağısına bakılmaz
elif puan >= 70:
harf = "CC"
else:
harf = "FF"
print(harf) # BBGirinti bir kuraldır
Python'da kod blokları süslü parantezle değil, yalnızca girintiyle belirlenir; bu bir tercih değil söz dizimi kuralıdır. PEP 8 stil rehberi her düzey için 4 boşluk önerir ve sekme ile boşluğun karıştırılmamasını ister. VS Code, PyCharm, Thonny gibi editörler Tab tuşunu otomatik 4 boşluğa çevirir.
| Hata | Yanlış | Doğru | Python ne der? |
|---|---|---|---|
| Karşılaştırma yerine atama | if x = 5: | if x == 5: | SyntaxError |
| İki nokta eksik | if x > 0 | if x > 0: | SyntaxError |
| Girinti eksik | Gövde if ile aynı hizada | 4 boşluk içeride | IndentationError |
| Tab ve boşluk karışık | Bir satır Tab, öteki boşluk | Yalnızca boşluk | TabError |
| elif sırası yanlış | Küçükten büyüğe | Büyükten küçüğe | Hiçbir şey: mantık hatası |
İç içe koşul
İkinci koşul ancak birincisi sağlanınca anlamlıysa koşullar iç içe yazılır: önce hesap aktif mi, aktifse bakiye yeterli mi? İç içe yapı, iki farklı durum için farklı mesaj vermeyi kolaylaştırır. Ama 3 düzeyden derin iç içelik okunabilirliği bozar; o zaman fonksiyona ya da and/or'a başvurulur.
hesap_aktif = True
bakiye = 1500.0
cekilecek = 400.0
if hesap_aktif:
if cekilecek <= bakiye:
bakiye -= cekilecek
print(f"Onaylandı. Kalan: {bakiye:.2f} TL")
else:
print("Yetersiz bakiye.")
else:
print("Hesap aktif değil.")Üçlü ifade ve match–case
Üçlü ifade (ternary), koşula göre tek satırda değer seçer: x if koşul else y. Basit durumda kodu kısaltır, karmaşık mantıkta okunabilirliği düşürür; üç ya da daha çok dal varsa elif'e dönmek daha sağlıklı.
yas = 20
durum = "Yetişkin" if yas >= 18 else "Çocuk"
def http_mesaj(kod):
match kod: # Python 3.10 ve sonrası
case 400:
return "Hatalı istek"
case 401 | 403: # 401 veya 403
return "Yetki hatası"
case 404:
return "Sayfa bulunamadı"
case _: # joker: hiçbiri uymazsa
return "Bilinmeyen hata"| if / elif / else | match / case | |
|---|---|---|
| Sürüm | Tüm sürümler | 3.10 ve sonrası (Ekim 2021) |
| Ne için? | Her tür koşul | Değer ve yapı eşleştirme (sabit, dizi, sözlük, sınıf, guard) |
| Birden çok değer | or ile | case 400 | 404: |
| Varsayılan dal | else: | case _: |
2. Döngüler: for ve while
Döngü, bir koşul sağlandıkça ya da bir koleksiyonun tüm ögeleri işlenene kadar aynı kodu tekrar tekrar çalıştıran yapıdır. Gövdenin bir kez çalışmasına yineleme (iteration), durumu takip eden değişkene döngü değişkeni denir. Pythonic adlandırma: liste urunler ise döngü değişkeni urun.
| Ölçüt | for | while |
|---|---|---|
| Tekrar sayısı | Önceden belli | Önceden belli olmayabilir |
| Koşulu kim yönetir? | Python | Programcı |
| Sonsuz döngü riski | Düşük | Yüksek |
| Kullanıcı girişi beklemek | Uygun değil | Çok uygun |
| Tipik kullanım | Liste, metin, range üzerinde gezmek | «Doğru şifre girilene kadar», «bağlantı kurulana kadar» |
for, range() ve enumerate()
Python'daki for, C ya da Java'daki sayaçlı döngüden farklıdır: bir yinelenebilir (iterable) nesnenin ögelerini tek tek gezer. Liste, demet, metin, sözlük ve range yerleşik yinelenebilirlerdir. Belli sayıda tekrar için range(start, stop, step) kullanılır; stop değeri dahil değildir.
range(5) # 0, 1, 2, 3, 4
range(2, 8) # 2 … 7
range(0, 20, 3) # 0, 3, 6, 9, 12, 15, 18
range(10, 0, -2) # 10, 8, 6, 4, 2 (geri sayım)
meyveler = ["elma", "muz", "çilek"]
for i, meyve in enumerate(meyveler, start=1): # range(len(...)) yerine
print(f"{i}. {meyve}")
toplam = 0 # birikim örüntüsü
for sayi in range(1, 101):
toplam += sayi
print(toplam) # 5050- →range() sayı listesi değil, tembel (lazy) bir nesne döndürür: sayıları istendikçe üretir. list(range(1_000_000)) yaklaşık 8 MB tutarken range(1_000_000) yalnızca 48 bayttır.
- →enumerate() her öge için (indeks, değer) çifti verir; range(len(liste)) ile elle indeks takibinden daha okunur ve Pythonic.
- →Birikim örüntüsü (accumulator): değişken döngüden önce sıfırlanır, her turda güncellenir, sonuç döngüden sonra yazdırılır. Sepet toplamı, ortalama, en büyük/en küçük hep böyle hesaplanır.
while ve sonsuz döngü
toplam = 0
sayi = 1 # 1) başlat
while sayi <= 100: # 2) her turda denetle
toplam += sayi
sayi += 1 # 3) güncelle: unutulursa sonsuz döngü!
while True: # sayısı belirsiz tekrar
cevap = input("Devam? (e/h): ")
if cevap == "h":
breakİç içe döngü ve maliyeti
for i in range(1, 6):
for j in range(1, 6):
print(f"{i*j:4}", end="")
print() # 5 × 5 = 25 kez iç gövdeHer dış turda iç döngü baştan sona çalışır. Tek döngü O(n), iki iç içe döngü O(n²), üç iç içe O(n³). Küçük tabloda fark edilmez, milyon satırlık veride süreyi saatlere çıkarır; önce sözlük araması, küme ya da vektörel işlem gibi alternatifleri düşün.
3. Döngü kontrolü: break, continue, else, pass
- →break: içinde bulunduğu en içteki döngüyü anında bitirir; kalan yinelemeler yok sayılır, akış döngüden sonraki ilk satırla sürer. «Aradığımı buldum» anı.
- →continue: döngüyü bitirmez; yalnızca o turun kalanını atlar ve sıradaki yinelemeye geçer.
- →pass: hiçbir şey yapmayan yer tutucu. Python boş blok kabul etmediği için henüz yazılmamış fonksiyon, if ya da döngü gövdesine konur. (… Ellipsis de geçerlidir.)
urunler = ["elma", "armut", "muz", "üzüm"]
for urun in urunler:
if urun == "muz":
print("Bulundu!")
break # üzüm hiç kontrol edilmez
for sayi in range(1, 11):
if sayi % 2 == 0:
continue # çiftleri atla
print(sayi) # 1 3 5 7 9Döngüye bağlı else
Python'a özgü bir yapı: for ya da while bloğunun hemen altına bir else yazılabilir ve bu else döngü break ile kesilmeden doğal yoldan bittiğinde çalışır. Tek cümlelik kural: «else, break olmadıysa çalışır.» return ya da bir istisna da else'i atlar. Bayrak değişkenine (bulundu = False) gerek bırakmaz.
dogru_sifre = "python2025"
for deneme in range(1, 4):
girilen = input(f"Şifre ({deneme}/3): ")
if girilen == dogru_sifre:
print("Giriş başarılı.")
break
print(f"Hatalı. {3 - deneme} hakkın kaldı.")
else: # 3 hak da bitti, break hiç olmadı
print("Hesap kilitlendi.")| Yanlış düşünce | Doğrusu |
|---|---|
| else, if-else'teki gibi «koşul yanlışsa» çalışır | else, döngü break ile kesilmediyse çalışır |
| Boş listede döngü hiç dönmez, else de çalışmaz | Gövde çalışmaz ama break de yoktur → else çalışır |
| else, içerideki if'e aittir | else for/while'a aittir; girintisi de bunu gösterir |
| return ya da hata olsa da else çalışır | return ve istisna da break gibi else'i atlar |
| break | continue | pass | return | |
|---|---|---|---|---|
| Döngüyü bitirir mi? | Evet (en içteki) | Hayır | Hayır | Evet (fonksiyon da biter) |
| O turu atlar mı? | Evet, kalan her şeyi | Evet, yalnızca o turu | Hayır | Evet |
| Loop-else'i atlar mı? | Evet | Hayır | Hayır | Evet |
| Nerede kullanılır? | for / while | for / while | Her blok | Yalnızca def içinde |
| İç içe döngüde | Yalnızca en içten çıkar | Yalnızca en içi etkiler | — | Tüm seviyelerden çıkar |
4. Hata ayıklama ve akış izleme
| Tür | Ne zaman fark edilir? | Örnek |
|---|---|---|
| Söz dizimi hatası (SyntaxError) | Kod çalışmaya başlamadan, ayrıştırma aşamasında; tek satır bile çalışmaz | for i in range(5) → iki nokta eksik |
| Çalışma zamanı hatası (exception) | Çalışırken; hatalı satıra kadar her şey çalışır, sonra durur ve traceback verir | sayilar[5] (3 elemanlı listede), "42" + 8, 10 / 0 |
| Mantık hatası | Python fark etmez; program sonuna kadar çalışır ama sonuç yanlış | 1–10 toplamı için range(1, 10) → 45 (55 olmalı) |
IndentationError ve TabError aslında SyntaxError'ın alt sınıflarıdır. SyntaxError mesajındaki ^ işareti yorumlayıcının durduğu yeri gösterir; gerçek hata çoğu zaman biraz öncesindedir. Mantık hatası ise bulunması en zor hatadır, çünkü uyarı yoktur: ancak beklenen çıktıyla gerçek çıktıyı karşılaştırarak yakalanır.
Traceback okumak
Traceback (most recent call last):
File "hesap.py", line 12, in <module>
hesapla(0)
File "hesap.py", line 8, in hesapla
return toplam / sayi
ZeroDivisionError: division by zero- →Traceback (hata izleme), hata anındaki çağrı yığınının raporudur. En yeni çağrı en alttadır.
- →Her iki satırlık blok bir çerçevedir: dosya, satır numarası, fonksiyon adı ve o satırdaki kod.
- →Son satır asıl bilgidir: HataTürü: mesaj. Okumaya en alttan başla, sonra yukarı çıkarak hataya giden yolu izle.
| Hata | Anlamı | Tipik çözüm |
|---|---|---|
| SyntaxError | Dil bilgisi ihlali (eksik :, parantez) | ^ işaretinin çevresine bak |
| IndentationError | Tutarsız girinti | Her yerde 4 boşluk |
| NameError | Tanımlanmamış değişken | Yazımı ve tanımlandığı yeri kontrol et |
| TypeError | Uyumsuz tiplerle işlem ("42" + 8) | type() ile bak; int(), str() ile dönüştür |
| ValueError | Tip doğru ama değer geçersiz (int("abc")) | Dönüştürmeden önce girdiyi doğrula |
| ZeroDivisionError | Sıfıra bölme | Paydayı önce kontrol et |
| IndexError | Liste sınırı dışı | len() ile sınırı doğrula |
| KeyError | Sözlükte olmayan anahtar | if anahtar in d ya da d.get(anahtar, varsayılan) |
| AttributeError | Nesnede olmayan nitelik | dir(nesne) ile mevcut nitelikleri incele |
| ModuleNotFoundError | Modül bulunamadı | Adını ve kurulumunu (pip install) kontrol et |
Akışı izlemek: print ve breakpoint()
Print debugging: şüpheli noktalara print() koyup değerleri izlemek. Kurulum gerektirmez, her yerde çalışır. Adımlar: hatanın bölgesini tahmin et, oradaki değişkenleri yazdır, beklenenle karşılaştır, düzelt ve print'leri kaldır. Python 3.8'den beri f-string'deki = işareti değişkenin adını da değerini de yazar. Büyük projelerde bu işi logging modülü üstlenir.
def ortalama(notlar):
print(f"{notlar = }") # notlar = [85, 90, 78]
toplam = sum(notlar)
print(f"{toplam = }") # toplam = 253
return toplam / len(notlar)
def faktoriyel(n):
breakpoint() # Python 3.7+: burada dur, (Pdb) istemi açılır
sonuc = 1
for i in range(1, n + 1):
sonuc *= i
return sonuc| pdb komutu | Kısaltma | İşlev |
|---|---|---|
| next | n | Sonraki satır; çağrılan fonksiyonun içine girmez (step over) |
| step | s | Sonraki satır; çağrılan fonksiyonun içine girer (step into) |
| continue | c | Sonraki kesme noktasına kadar devam |
| list | l | Bulunulan yerin çevresindeki 11 satırı göster |
| p ifade | Bir ifadenin değerini yazdır | |
| quit | q | Hata ayıklayıcıdan çık |
VS Code ve PyCharm aynı işi görsel yapar: satır numarasının yanına tıklayıp kesme noktası koyarsın, Debug modunda değişkenler yan panelde canlı görünür (PyCharm'da F8 step over, F7 step into).
Yardım istemenin doğru yolu
- →Aramaya «hata aldım» yazma; hata türünü ve mesajını olduğu gibi kopyala ve başına dili ekle: Python ZeroDivisionError: division by zero.
- →Dosya adı, kendi değişken adların gibi sana özgü ayrıntıları çıkar; başkasında aynısı olmaz.
- →Çözüm ve örnek kod içeren, çok oy almış cevaplara öncelik ver.
- →Tinkering (rastgele kurcalama): kodu anlamadan küçük değişiklikler yapıp tekrar tekrar çalıştırmak. Bir araştırmada öğrenciler alıştırma başına ortalama 13 kez çalıştırıp her seferinde yalnızca ~2 karakter değiştirmiş; bu yolu seçenlerin başarısı %44 ile sınırlı kalmış.
Kendini test et!
Cevabı görmek için soruya dokun.
1.elif zincirinde birden çok koşul doğruysa hangisi çalışır?
✓ Yalnızca en üstteki ilk doğru koşul; zincirin gerisine bakılmaz.
2.list(range(3, 12, 4)) neyi üretir?
✓ [3, 7, 11]. Durma değeri 12 dahil değildir.
3.break ile continue arasındaki fark nedir?
✓ break döngüyü tamamen bitirir; continue yalnızca o turun kalanını atlayıp sıradaki tura geçer.
4.Döngüye bağlı else hangi durumda çalışmaz?
✓ Döngü break ile kesilirse (ya da return veya istisna olursa).
5.Traceback'in hangi satırını önce okumalısın?
✓ En alttakini: hata türü ve mesajı oradadır.
6.Program hatasız çalışıyor ama ortalamayı yanlış hesaplıyor. Bu hangi tür hatadır?
✓ Mantık hatası.
Deneme testi
Sınavda çıkabilecek türden 10 soru. Bir şık seç; doğru cevap ve açıklaması hemen çıkar.
1.x = 0 iken «if x: print('A') else: print('B')» yapısı ekrana ne yazar?
2.puan = 75 için sırasıyla «puan >= 50 → C», «puan >= 70 → B», «puan >= 90 → A» koşullarından oluşan bir if–elif zinciri hangi notu verir?
3.Aynı blokta bazı satırlar Tab, bazıları boşlukla girintilenmişse hangi hata alınır?
4.list(range(10, 0, -3)) ifadesinin sonucu nedir?
5.Kullanıcı «q» yazana kadar komut alacak bir program için en uygun yapı hangisidir?
6.Aşağıdaki kod ne yazdırır? for i in range(1, 6): if i % 2 == 0: continue if i == 5: break print(i) else: print('bitti')
7.İç içe iki for döngüsünde iç döngüdeki break çalışınca ne olur?
8.Henüz içi yazılmamış bir fonksiyonun gövdesine söz dizimi hatası almamak için ne konur?
9.liste = [3, 6, 9] iken print(liste[3]) çalıştırılırsa hangi hata oluşur?
10.pdb'de çağrılan bir fonksiyonun içine girerek satır satır ilerlemek için hangi komut kullanılır?
Bu not ders kitabının yerine geçmez; konu kendi cümlelerimizle, yapay zekâ desteğiyle özetlendi.