while Döngüsü
for döngüsü "şu koleksiyondaki her eleman için" derken, while döngüsü "şu koşul doğru olduğu sürece devam et" der. İkisi arasındaki fark bu kadar net. while, kaç kez döneceğini önceden bilmediğin durumlarda parlar — kullanıcıdan input beklerken, bir dosyanın sonuna ulaşana kadar okurken, veya bir koşul sağlanana kadar deneme yaparken.
Bir musluk analojisi düşün: Musluğu açtın, bardak doluyor. "Bardak dolana kadar bekle" — bu bir while döngüsü. Ne zaman dolacağını tam bilemezsin ama dolunca musluğu kapatırsın. İşte while böyle çalışır: koşul True olduğu sürece döner, False olduğu an durur.
Temel Söz Dizimi
sayac = 1
while sayac <= 5:
print(f"Sayaç: {sayac}")
sayac += 1Çıktı:
Sayaç: 1
Sayaç: 2
Sayaç: 3
Sayaç: 4
Sayaç: 5Yapı:
whileanahtar kelimesiKoşul ifadesi (boolean sonuç döndüren)
:ve girintili kod bloğu
Her döngü turunda Python önce koşulu kontrol eder. Koşul True ise bloğu çalıştırır, sonra tekrar kontrol eder. False olduğu an döngüden çıkar.
Akış Diyagramı
[Koşulu kontrol et] → True → [Kod bloğunu çalıştır] → [Başa dön]
↓ False
[Döngüden çık]Kritik Nokta: Koşulun Bir Noktada False Olması Gerekir
# ⚠️ sayac değişmezse sonsuz döngü!
sayac = 1
while sayac <= 5:
print(f"Sayaç: {sayac}")
# sayac += 1 unutulmuş! → Sonsuz döngü!Her while döngüsünde kendine şu soruyu sor: "Bu koşul bir noktada `False` olacak mı?" Eğer cevap emin değilim ise, kodunda bir problem var demektir.
while vs for: Ne Zaman Hangisi?
İki döngü türü farklı senaryolara uygundur:
| Senaryo | Tercih | Neden |
|---|---|---|
| Liste/koleksiyon üzerinde dönme | for | Eleman sayısı belli |
| N kere tekrarlama | for + range() | Sayı belli |
| Koşula bağlı dönme | while | Ne zaman biteceği belirsiz |
| Kullanıcı input bekleme | while | Kullanıcıya bağlı |
| Dosya sonuna kadar okuma | for | Dosya iterable |
| Yakınsama/convergence | while | Sonuç belirsiz |
# for uygun — eleman sayısı belli
isimler = ["Ahmet", "Ayşe", "Mehmet"]
for isim in isimler:
print(isim)
# while uygun — kaç deneme olacağı belirsiz
import random
hedef = random.randint(1, 100)
tahmin = 0
while tahmin != hedef:
tahmin = int(input("Tahminin: "))
print("Doğru tahmin!")Genel kural: Bir iterable üzerinde dönüyorsan `for`, koşula bağlı dönüyorsan `while` kullan.
Sonsuz Döngü: while True + break
Bazen döngünün ortasında veya sonunda çıkış kararı vermek istersin. Bu durumda while True ile sonsuz döngü başlatıp, break ile çıkarsın.
while True:
cevap = input("Devam etmek istiyor musun? (e/h): ")
if cevap.lower() == "h":
print("Hoşçakal!")
break
print("Devam ediyoruz...")Bu pattern çok yaygın ve güçlü. Özellikle:
Önce çalıştır, sonra kontrol et (do-while benzeri)
Birden fazla çıkış noktası olan döngüler
Menü sistemleri
Python'da do-while Yok!
C, Java gibi dillerde do-while döngüsü vardır — önce bloğu çalıştırır, sonra koşulu kontrol eder. Python'da bu yapı yok ama while True + break ile simüle edebilirsin:
# C'deki do-while karşılığı
while True:
sayi = int(input("Pozitif sayı girin: "))
if sayi > 0:
break
print("Hatalı giriş! Tekrar deneyin.")
print(f"Girdiğiniz sayı: {sayi}")Bu kod en az bir kere input alır (do-while davranışı), sonra koşulu kontrol eder.
while-else Yapısı
for-else gibi, while döngüsüne de else bloğu ekleyebilirsin. Mantık aynı: döngü `break` ile kesilmeden, koşul `False` olarak normal şekilde sona erdiyse `else` çalışır.
deneme = 0
max_deneme = 3
while deneme < max_deneme:
sifre = input(f"Şifre ({deneme + 1}/{max_deneme}): ")
if sifre == "gizli123":
print("Giriş başarılı!")
break
deneme += 1
else:
print("3 deneme hakkınız doldu. Hesap kilitlendi!")Burada:
Doğru şifre girilirse →
breakçalışır →elseatlanır3 deneme başarısız olursa → koşul
Falseolur →elseçalışır
Bu, "deneme hakkı" senaryoları için mükemmel bir yapı.
Başka Bir Örnek: Arama
import random
hedef = 42
denemeler = []
sayac = 0
while sayac < 100:
tahmin = random.randint(1, 100)
denemeler.append(tahmin)
if tahmin == hedef:
print(f"{len(denemeler)}. denemede bulundu!")
break
sayac += 1
else:
print(f"100 denemede {hedef} bulunamadı.")Sentinel Value Pattern
Sentinel value (nöbetçi değer), döngünün sonunu belirten özel bir değerdir. Kullanıcıdan art arda girdi alırken yaygın olarak kullanılır.
# -1 sentinel değer olarak
print("Sayıları girin (-1 ile bitirin):")
toplam = 0
sayi_adedi = 0
while True:
girdi = int(input("Sayı: "))
if girdi == -1: # Sentinel değer
break
toplam += girdi
sayi_adedi += 1
if sayi_adedi > 0:
ortalama = toplam / sayi_adedi
print(f"Toplam: {toplam}")
print(f"Ortalama: {ortalama:.2f}")
else:
print("Hiç sayı girilmedi.")Sentinel Value Seçimi Önemli
Sentinel değer, normal veri aralığında olmamalıdır. Eğer kullanıcı negatif sayılar da girebiliyorsa, -1 kötü bir sentinel olur. Bu durumda string tabanlı sentinel kullanabilirsin:
print("Sayıları girin ('q' ile bitirin):")
sayilar = []
while True:
girdi = input("Sayı: ")
if girdi.lower() == "q":
break
try:
sayilar.append(float(girdi))
except ValueError:
print("Geçersiz giriş, tekrar deneyin.")
print(f"Girilen sayılar: {sayilar}")Dosya Okumada Sentinel
# iter() ile sentinel pattern — çok Pythonic!
# İki argümanlı iter: iter(callable, sentinel)
# Dosyadan satır satır oku, boş satıra kadar
import io
dosya = io.StringIO("satır 1\nsatır 2\nsatır 3\n\nsonra bunlar okunmaz")
for satir in iter(dosya.readline, "\n"):
print(satir.strip())
# satır 1
# satır 2
# satır 3iter(callable, sentinel) formu, callable'ı çağırmaya devam eder ve sentinel değerini döndürdüğünde durur. Bu çok zarif bir Python pattern'ı.
Counter Pattern (Sayaç Deseni)
En temel while pattern'ı: bir sayacı artırarak belirli bir limite kadar dönmek.
# Temel counter
i = 0
while i < 10:
print(i, end=" ")
i += 1
# 0 1 2 3 4 5 6 7 8 9Ama bu genellikle for i in range(10) ile daha temiz yazılır. Counter pattern'ın gerçek gücü koşullu artırma gerektiğinde ortaya çıkar:
# Koşullu counter — for ile yapmak zor
i = 1
while i <= 100:
if i % 7 == 0 and i % 3 != 0:
print(i, end=" ")
i += 1 if i % 2 == 0 else 2 # Dinamik adım!Geri Sayım
def geri_sayim(n):
while n > 0:
print(n, end="... ")
n -= 1
print("Kalkış! 🚀")
geri_sayim(5)
# 5... 4... 3... 2... 1... Kalkış! 🚀Collatz Conjecture (Matematiksel Örnek)
Collatz hipotezi: Herhangi bir pozitif tam sayıyla başla. Çiftse 2'ye böl, tekse 3 ile çarp 1 ekle. Sonunda her zaman 1'e ulaşır (henüz kanıtlanmamış!).
n = 27
adim = 0
print(f"Başlangıç: {n}")
while n != 1:
if n % 2 == 0:
n = n // 2
else:
n = 3 * n + 1
adim += 1
print(f"Adım {adim}: {n}")
print(f"\n{adim} adımda 1'e ulaşıldı.")input() ile Kullanıcı Menüsü
while True döngüsü, etkileşimli menü sistemleri için mükemmel:
def ana_menu():
while True:
print("\n" + "=" * 30)
print(" 📋 ANA MENÜ")
print("=" * 30)
print("1. Yeni kayıt ekle")
print("2. Kayıtları listele")
print("3. Kayıt ara")
print("4. Kayıt sil")
print("0. Çıkış")
print("=" * 30)
secim = input("Seçiminiz: ").strip()
if secim == "1":
yeni_kayit_ekle()
elif secim == "2":
kayitlari_listele()
elif secim == "3":
kayit_ara()
elif secim == "4":
kayit_sil()
elif secim == "0":
print("Güle güle! 👋")
break
else:
print("❌ Geçersiz seçim! Tekrar deneyin.")Gelişmiş Menü: Alt Menüler
kayitlar = []
def yeni_kayit_ekle():
isim = input("İsim: ").strip()
if not isim:
print("İsim boş olamaz!")
return
yas = input("Yaş: ").strip()
try:
yas = int(yas)
except ValueError:
print("Yaş sayı olmalı!")
return
kayitlar.append({"isim": isim, "yas": yas})
print(f"✅ {isim} eklendi.")
def kayitlari_listele():
if not kayitlar:
print("Henüz kayıt yok.")
return
print(f"\n{'İsim':<15} {'Yaş':<5}")
print("-" * 20)
for kayit in kayitlar:
print(f"{kayit['isim']:<15} {kayit['yas']:<5}")Input Doğrulama Döngüsü
Kullanıcıdan geçerli bir giriş alana kadar sormaya devam et:
def pozitif_sayi_al(mesaj="Pozitif sayı girin: "):
while True:
try:
sayi = float(input(mesaj))
if sayi > 0:
return sayi
print("Sayı pozitif olmalı!")
except ValueError:
print("Geçerli bir sayı girin!")
# Kullanım
fiyat = pozitif_sayi_al("Ürün fiyatı: ")
print(f"Fiyat: {fiyat:.2f} TL")Bu pattern çok yaygın: while True + try-except + return. Geçerli değer gelene kadar döner, gelince fonksiyondan çıkar.
def evet_hayir_sor(soru):
while True:
cevap = input(f"{soru} (e/h): ").strip().lower()
if cevap in ("e", "evet"):
return True
elif cevap in ("h", "hayır"):
return False
print("Lütfen 'e' veya 'h' girin.")
# Kullanım
if evet_hayir_sor("Devam etmek istiyor musun?"):
print("Devam ediyoruz!")
else:
print("İptal edildi.")Sonsuz Döngü Tehlikesi ve Debug İpuçları
Sonsuz döngüler, özellikle yeni başlayanların en sık düştüğü tuzaklardan biri. Programın takılıp kalması, belleğin dolması, CPU'nun %100'e çıkması... Hepsi sonsuz döngü belirtisi.
⚠️ Dikkat: Sonsuz döngüye girdiğini anlaman için şu belirtilere dikkat et: - Terminal yanıt vermiyor, imlec yanıp sönüyor - CPU kullanımı %100'e çıkıyor - Bilgisayarın fanı çılgınca dönmeye başlıyor - Çıkış için
Ctrl + C(KeyboardInterrupt) kullan!
Yaygın Sonsuz Döngü Hataları
Hata 1: Sayacı artırmayı unutma
# ❌ Sonsuz döngü
i = 0
while i < 10:
print(i)
# i += 1 unutulmuş!
# ✅ Düzeltme
i = 0
while i < 10:
print(i)
i += 1Hata 2: Yanlış koşul yönü
# ❌ Sonsuz döngü — i hiç 10'dan küçük olmayacak
i = 10
while i > 0:
print(i)
i += 1 # Artıyor, azalması gerekirken!
# ✅ Düzeltme
i = 10
while i > 0:
print(i)
i -= 1Hata 3: Float karşılaştırma sorunu
# ❌ Potansiyel sonsuz döngü — kayan nokta aritmetiği
x = 0.0
while x != 1.0:
x += 0.1
print(f"{x:.20f}")
# 0.1 + 0.1 + ... tam olarak 1.0 yapmayabilir!
# ✅ Düzeltme — eşikle karşılaştır
x = 0.0
while x < 1.0:
x += 0.1
print(f"{x:.1f}")Debug Stratejileri
Strateji 1: Maksimum iterasyon limiti koy
MAX_ITER = 1000
sayac = 0
while kosul and sayac < MAX_ITER:
# ... işlemler ...
sayac += 1
if sayac >= MAX_ITER:
print("UYARI: Maksimum iterasyon limitine ulaşıldı!")Strateji 2: Debug print'leri ekle
while kosul:
print(f"DEBUG: sayac={sayac}, kosul={kosul}") # Debug
# ... işlemler ...
sayac += 1Strateji 3: Watchdog timer (ileri seviye)
import time
baslangic = time.time()
TIMEOUT = 5 # 5 saniye
while kosul:
if time.time() - baslangic > TIMEOUT:
print("TIMEOUT: Döngü 5 saniyeyi aştı!")
break
# ... işlemler ...💡 İpucu: Geliştirme sırasında while döngülerinin içine geçici bir
input("Enter'a bas...")satırı ekle. Bu sayede her turda durur ve değişkenleri inceleyebilirsin. Debug bitince kaldır.
Gelişmiş Örnekler
Örnek 1: Sayı Tahmin Oyunu
import random
hedef = random.randint(1, 100)
kalan_hak = 7
tahminler = []
print("🎯 Sayı Tahmin Oyunu!")
print(f"1-100 arası bir sayı tuttum. {kalan_hak} hakkın var.\n")
while kalan_hak > 0:
try:
tahmin = int(input(f"Tahminin ({kalan_hak} hak): "))
except ValueError:
print("Lütfen bir sayı gir!")
continue
tahminler.append(tahmin)
kalan_hak -= 1
if tahmin == hedef:
print(f"\n🎉 Tebrikler! {len(tahminler)} denemede buldun!")
print(f"Tahminlerin: {tahminler}")
break
elif tahmin < hedef:
print("📈 Daha büyük!")
else:
print("📉 Daha küçük!")
else:
print(f"\n😞 Hakkın bitti! Sayı {hedef} idi.")
print(f"Tahminlerin: {tahminler}")Örnek 2: Newton-Raphson Karekök Hesaplama
def karekok(n, tolerans=1e-10):
"""Newton-Raphson yöntemiyle karekök hesapla."""
if n < 0:
raise ValueError("Negatif sayının karekökü hesaplanamaz")
if n == 0:
return 0
tahmin = n / 2 # İlk tahmin
iterasyon = 0
while True:
yeni_tahmin = (tahmin + n / tahmin) / 2
iterasyon += 1
# Yeterince yaklaştık mı?
if abs(yeni_tahmin - tahmin) < tolerans:
print(f"{iterasyon} iterasyonda yakınsadı")
return yeni_tahmin
tahmin = yeni_tahmin
sonuc = karekok(2)
print(f"√2 ≈ {sonuc}") # 1.4142135623730951
print(f"Doğrulama: {sonuc**2}") # 2.0000000000000004Bu, while döngüsünün ideal kullanımı: kaç iterasyon gerekeceğini önceden bilemezsin, yakınsama kriterine ulaşana kadar devam edersin.
Örnek 3: Basit Bekleme Mekanizması
import time
def bekle_ve_kontrol(max_sure=10, aralik=2):
"""Bir koşulun sağlanmasını bekle."""
baslangic = time.time()
while True:
gecen_sure = time.time() - baslangic
# Timeout kontrolü
if gecen_sure > max_sure:
print(f"⏰ {max_sure} saniye doldu — timeout!")
return False
# Koşul kontrolü (simüle)
import random
durum = random.choice([True, False, False, False])
if durum:
print(f"✅ Koşul {gecen_sure:.1f} saniyede sağlandı!")
return True
print(f"⏳ Bekleniyor... ({gecen_sure:.1f}s)")
time.sleep(aralik)
bekle_ve_kontrol()Örnek 4: İki Pointer Tekniği
# Palindrom kontrolü — iki uçtan ortaya doğru
def palindrom_mu(metin):
metin = metin.lower().replace(" ", "")
sol = 0
sag = len(metin) - 1
while sol < sag:
if metin[sol] != metin[sag]:
return False
sol += 1
sag -= 1
return True
test_kelimeleri = ["kayak", "kazak", "python", "abba", "racecar"]
for kelime in test_kelimeleri:
sonuc = "✅" if palindrom_mu(kelime) else "❌"
print(f"{sonuc} '{kelime}'")while ile İleri Pattern'lar
State Machine (Durum Makinesi)
durum = "BASLANGIC"
while durum != "BITIS":
if durum == "BASLANGIC":
print("Sistem başlatılıyor...")
durum = "HAZIR"
elif durum == "HAZIR":
komut = input("Komut (calistir/kapat): ")
if komut == "calistir":
durum = "CALISIYOR"
elif komut == "kapat":
durum = "BITIS"
elif durum == "CALISIYOR":
print("İşlem yapılıyor...")
import time
time.sleep(1)
print("İşlem tamamlandı.")
durum = "HAZIR"
print("Sistem kapatıldı.")Retry Pattern (Yeniden Deneme)
import time
import random
def api_cagri():
"""Rastgele başarılı/başarısız olan API simülasyonu."""
if random.random() < 0.7: # %70 başarısız
raise ConnectionError("Bağlantı hatası!")
return {"data": "başarılı"}
max_deneme = 5
deneme = 0
bekleme = 1 # Başlangıç bekleme süresi (saniye)
while deneme < max_deneme:
try:
sonuc = api_cagri()
print(f"✅ Başarılı: {sonuc}")
break
except ConnectionError as e:
deneme += 1
if deneme < max_deneme:
print(f"❌ Deneme {deneme}/{max_deneme}: {e}")
print(f" {bekleme}s sonra tekrar denenecek...")
time.sleep(bekleme)
bekleme *= 2 # Exponential backoff
else:
print(f"💀 {max_deneme} deneme başarısız!")Exponential backoff: Her başarısız denemede bekleme süresini ikiye katla (1s, 2s, 4s, 8s...). Gerçek dünya API çağrılarında standart bir pratik.
Performans ve Best Practice
1. while yerine for Tercih Et (Mümkünse)
# ❌ while ile — hata riski daha yüksek
i = 0
while i < len(liste):
print(liste[i])
i += 1
# ✅ for ile — daha güvenli ve okunabilir
for item in liste:
print(item)2. Koşulu Basit Tut
# ❌ Karmaşık koşul
while not (x > 10 and y < 5) or (z == 0 and w != None):
pass
# ✅ Koşulu değişkene ata
devam_et = not (x > 10 and y < 5) or (z == 0 and w is not None)
while devam_et:
# ... işlemler ...
devam_et = not (x > 10 and y < 5) or (z == 0 and w is not None)3. Sonsuz Döngüye Güvenlik Ağı
# Her zaman bir güvenlik ağı koy
MAX_ITER = 10_000
iterasyon = 0
while kosul:
iterasyon += 1
if iterasyon > MAX_ITER:
raise RuntimeError(f"Döngü {MAX_ITER} iterasyonu aştı!")
# ... işlemler ...Özet
`while koşul:` koşul
Trueolduğu sürece çalışır — kaç kez döneceği önceden bilinmeyen durumlarda kullan.`while True` + `break` sonsuz döngü pattern'ı, do-while simülasyonu ve menü sistemleri için ideal — Python'da do-while yok, bu onun karşılığı.
`while-else` döngü break olmadan, koşul False olarak normal sona erdiyse else çalışır — deneme hakkı senaryolarında kullanışlı.
Sentinel value pattern'ı döngünün sonunu belirten özel bir değerdir — kullanıcı input'unda yaygın (ör. "q" ile çıkış).
Input doğrulama döngüsü (
while True+try-except+return) geçerli giriş alana kadar sormaya devam eder.Sonsuz döngü en yaygın hata — sayacı artırmayı unutma, float karşılaştırmalarına dikkat et ve güvenlik ağı olarak MAX_ITER limiti koy.
AI Asistan
Sorularını yanıtlamaya hazır