← Kursa Dön
📄 Text · 12 min

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ç: 5

Yapı:

  • while anahtar kelimesi

  • Koş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:

SenaryoTercihNeden
Liste/koleksiyon üzerinde dönmeforEleman sayısı belli
N kere tekrarlamafor + range()Sayı belli
Koşula bağlı dönmewhileNe zaman biteceği belirsiz
Kullanıcı input beklemewhileKullanıcıya bağlı
Dosya sonuna kadar okumaforDosya iterable
Yakınsama/convergencewhileSonuç 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:

  1. Önce çalıştır, sonra kontrol et (do-while benzeri)

  2. Birden fazla çıkış noktası olan döngüler

  3. 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 → else atlanır

  • 3 deneme başarısız olursa → koşul False olur → 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 3

iter(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 9

Ama 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 += 1

Hata 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 -= 1

Hata 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 += 1

Strateji 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.0000000000000004

Bu, 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 True olduğ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.