while döngüsü ve kod izleme

Geçen hafta koşulun sonucuna göre hangi bloğun çalışacağını seçtik. Seçilen blok en fazla bir kez çalıştı. Oysa bazı işlerde aynı adımları koşul doğru olduğu sürece tekrar etmek gerekir.

Kullanıcı geçerli bir değer girene kadar yeniden sormak, en fazla üç deneme hakkı vermek, ölçümleri sırayla tek tek işlemek ya da birikim hedefe ulaşana kadar her hafta para eklemek bu türden işlerdir. Python’da koşula bağlı tekrar için while döngüsü kullanılır.

Bu hafta söz diziminden çok şuna çalışacağız: döngü her döndüğünde, yani her yinelemede, değişkenlerin nasıl değiştiğini izlemek ve döngünün neden durduğunu açıklamak.

Bu bölümün kapsamı

NoteSınavda sorulur
  • while koşulunun her yinelemeden önce sınanması
  • Koşul başta yanlışsa gövdenin hiç çalışmaması
  • Başlangıç, koşul ve güncellemenin birlikte kurulması
  • Sonsuz döngünün nedeni
  • Kod izleme tablosuyla her yinelemedeki değerleri izleme
  • Sınırın koşula dâhil edilip edilmemesinden doğan off-by-one hatası
  • Sayaç ile biriktiricinin ayrımı
  • Döngülerin çalışma süresi ve hız karşılaştırması
  • Çalışan programı Ctrl+C ile kesme (derste kullanılır, sınavda sorulmaz)
  • while ile birlikte kullanılan else bloğu

Bu başlıklar konunun devamıdır; ileride karşınıza çıkar ama bu derste ezberlemeniz beklenmiyor.

Bu döngü kaç kez çalışır?

Döngünün kaç tur döneceğini üç şey belirler: nereden başladığı, ne zaman duracağı ve her turda neyin değiştiği. Bu üçü birbirini tutmazsa döngü ya bir eksik ya bir fazla çalışır ya da hiç durmaz.

while: koşul doğru olduğu sürece tekrar et

while döngüsünde koşul kontrolü, gövde, güncelleme ve koşula geri dönüş akışı.

while döngüsünün akışı

En basit hâli şöyledir:

sayac = 1

while sayac <= 3:
    print(sayac)
    sayac = sayac + 1

Programın çalışma sırası:

  1. sayac <= 3 koşulu kontrol edilir.
  2. Koşul True ise döngü gövdesi çalışır.
  3. sayac bir artırılır.
  4. Program yeniden while satırına döner.
  5. Koşul False olduğunda döngü biter.

Program şunu yazdırır:

1
2
3

while koşulu her yinelemeden önce kontrol edilir. Bu nedenle başlangıçta koşul False ise döngü gövdesi hiç çalışmaz.

Tahmin et: döngü kaç kez çalışır?

Aşağıdaki kodu çalıştırmadan önce çıktı satırlarını tahmin edin:

Döngü gövdesi sayac değerleri 2, 4 ve 6 iken çalışır. sayac 8 olduğunda koşul False olur.

Yalnızca kaç satır yazdırıldığını saymayın. Her yinelemede şu üç şeye bakın:

  • Döngü başındaki sayac değeri
  • Koşulun sonucu
  • Gövdenin sonunda sayacın aldığı yeni değer

Kod izleme tablosu

Kısa döngülerde değişkenleri akılda tutabiliriz, ama döngü uzadıkça yanılmak kolaylaşır. O zaman bir kod izleme tablosu çizeriz: her satır bir yinelemeyi, her sütun bir değişkenin o andaki değerini gösterir.

Şu programı izleyelim:

sayac = 1
toplam = 0

while sayac <= 4:
    toplam = toplam + sayac
    sayac = sayac + 1

print(toplam)

İzleme tablosu:

Yineleme Döngü başında sayac toplam sonrası Gövde sonunda sayac
1 1 1 2
2 2 3 3
3 3 6 4
4 4 10 5

Sonraki kontrolde 5 <= 4 sonucu False olur ve döngü biter. Ekrana 10 yazdırılır.

Döngü içinde değişkenlerin tur tur nasıl değiştiğini gösteren kod izleme tablosu.

Kod izleme
Tip

Döngüde hata ararken yalnızca sonuca bakmayın. İlk birkaç yinelemede değişken değerlerini tabloya yazarsanız hatanın hangi adımda başladığını görürsünüz.

Sayaç neden güncellenir?

Sayaç, döngünün kaçıncı turda olduğunu gösterir. Döngünün bir gün durması şu satıra bağlıdır:

sayac = sayac + 1

Bu satır olmasaydı sayac sürekli 1 kalır ve sayac <= 3 koşulu hep True olurdu.

İncele ve düzelt: sonsuz döngü

Aşağıdaki programdaki hata bilerek bırakıldı. Program 1, 2, 3 değerlerini yazdırıp durmalı.

Eksik sayaç güncellemesini ekleyin.

print(sayac) satırından sonra sayac = sayac + 1 ekleyebilirsiniz.

sayac = 1

while sayac <= 3:
    print(sayac)
    sayac = sayac + 1
Warning

Bu sayfadaki hücrelerin bir süre sınırı var. Kendi bilgisayarınızda ise sonsuz döngü işlemciyi boş yere meşgul edebilir. Program terminalde (VS Code terminali dâhil) durmuyorsa Ctrl+C ile çalışan Python programını kesebilirsiniz. Python bu durumda çoğunlukla KeyboardInterrupt yazar. VS Code’un çalıştırma görünümündeki Stop düğmesi de aynı işi görür.

Döngü yazarken kendinize mutlaka sorun: “Bu koşulu bir gün False yapacak değişiklik nerede?” Ctrl+C koddaki hatayı düzeltmez, yalnızca yanlışlıkla başlattığınız programı durdurur.

off-by-one hatası

Döngünün istenenden bir kez fazla ya da bir kez az çalışmasına off-by-one hatası denir.

Örneğin 1’den 5’e kadar sayıları yazdırmak istiyoruz:

sayac = 1

while sayac < 5:
    print(sayac)
    sayac = sayac + 1

Bu program 5 değerini yazdırmaz. Koşul sayac <= 5 olmalıdır.

Sınır değerlerini düşünmek burada da işe yarar:

  • İlk çalışması gereken değer: 1
  • Son çalışması gereken değer: 5
  • İlk çalışmaması gereken değer: 6

Alıştırma: geri sayımı düzeltin

Amaç 5, 4, 3, 2, 1 değerlerini yazdırmaktır. Mevcut kod 1 değerini atlıyor.

Koşulu düzeltin.

> yerine >= kullanmayı düşünün.

sayac = 5

while sayac >= 1:
    print(sayac)
    sayac = sayac - 1

Başlangıç değeri de sonucu etkiler

Döngünün koşulu doğru olsa bile başlangıç değeri yanlışsa sonuç yine hatalı olabilir.

sayac = 0

while sayac <= 5:
    print(sayac)
    sayac = sayac + 1

Bu program 0’ı da yazdırır. 1–5 aralığını yazdırmak istiyorsak sorun koşulda değil, başlangıç değerindedir.

Bu yüzden sayaç döngülerinde üç parçayı birlikte kontrol edin:

başlangıç değeri → devam koşulu → güncelleme

Bunlardan biri yanlışsa döngü beklenenden farklı sayıda çalışabilir.

Değiştir: deneme hakkını izleyin

Bir giriş ekranının kullanıcıya en fazla 3 deneme hakkı verdiğini düşünelim. Burada parola sormuyoruz, yalnızca denemeleri sayıyoruz.

Şunları sırayla deneyin:

  1. En fazla 5 deneme olacak biçimde değiştirin.
  2. İlk satırda Deneme: 0 yazdıracak bir başlangıç değeri verin. Kaç satır yazdırıldığına bakın.
  3. Koşulu < 3 yapın. Kaç deneme yazdırılacağını tahmin edin.
  4. Her değişiklikte programı çalıştırmadan önce kaç yineleme olacağını yazın.

Hedefe ulaşana kadar değer biriktirmek

Döngüde yalnızca sayaç yazdırmayız. Her yinelemede başka bir değeri de güncelleyebiliriz.

Örneğin her hafta 250 TL biriktiren birinin 1000 TL’ye kaç haftada ulaştığını izleyelim:

Burada iki değişken değişir:

  • birikim: şimdiye kadar biriken parayı tutar.
  • hafta: kaç yineleme yapıldığını sayar.

hafta bir sayaçtır: her turda 1 artar. birikim ise bir biriktiricidir (accumulator): her turda üstüne yeni bir değer eklenir ve biriken sonucu tutar.

Döngü birikim < 1000 koşulu False olduğunda biter.

Alıştırma: hedefe kaç günde ulaşılır?

Bir kişi her gün 1200 adım atıyor ve toplamda 6000 adıma ulaşmak istiyor. Programı, bu hedefe kaç günde ulaşılacağını hesaplayacak biçimde tamamlayın.

Gövde içinde iki güncelleme gerekir: toplam_adim = toplam_adim + 1200 ve gun = gun + 1.

toplam_adim = 0
gun = 0

while toplam_adim < 6000:
    toplam_adim = toplam_adim + 1200
    gun = gun + 1

print("Gün:", gun)
print("Toplam adım:", toplam_adim)

Kullanıcı girdisini tekrar istemek

Geçerli değer gelene kadar kullanıcıdan yeniden girdi alma akışı.

Koşullu tekrar

while ile kullanıcıya geçerli bir değer girene kadar yeniden sorabiliriz. Örneğin yalnızca 1–5 arasında puan kabul eden bir program:

puan = int(input("1-5 arasında puan: "))

while puan < 1 or puan > 5:
    print("Geçersiz değer")
    puan = int(input("1-5 arasında puan: "))

print("Kabul edilen puan:", puan)

Bu örnekte ilk girdi geçerliyse döngü hiç çalışmaz. Geçersizse yeni değer alınır ve koşul yeniden sınanır.

Aynı input() satırı iki kez yazıldı: döngüden önce ve döngünün içinde. Öndeki satır, while koşulu ilk kez sınanırken puan değişkeninin bir değeri olsun diye var. Bu kalıp çok kullanılır ama aynı satırı iki kez yazmayı gerektirir.

NoteBu tekrarı gelecek hafta kaldıracağız

Beşinci bölümde break öğrendiğimizde aynı problemi while True: ile tek bir input() satırı kullanarak yazabileceğiz: girdiyi al, geçerliyse döngüden çık, değilse yeniden dene. break henüz işlenmediği için bu hafta bu biçimi bilerek kullanıyoruz.

Note

Bu hafta girdinin int() ile dönüştürülebilen bir sayı olduğunu varsayıyoruz. "abc" gibi sayıya çevrilemeyen girdileri istisnalar konusuna geldiğimizde ele alacağız.

Üret: cihaz şarjını hedefe ulaştırın

Bir cihazın şarjı başlangıçta %20 olsun. Her şarj adımında seviye 15 puan artsın. Şarj seviyesi en az %80 olduğunda döngü durmalı.

Aşağıdaki başlangıç kodunu tamamlayın:

Kabul kriterleri:

  • Döngü sarj < 80 olduğu sürece çalışmalı.
  • Her yinelemede sarj değeri 15 artmalı.
  • adim değeri her yinelemede 1 artmalı.
  • Döngü sonunda sarj en az 80 olmalı.

Döngü while sarj < 80: satırıyla başlar. Gövdede iki ayrı değişkeni güncelleyin.

sarj = 20
adim = 0

while sarj < 80:
    sarj = sarj + 15
    adim = adim + 1

print("Son şarj:", sarj)
print("Adım sayısı:", adim)

Sınav provası

Önce kendi cevabınızı seçin, sonra cevap anahtarında her şıkkın neden doğru ya da yanlış olduğunu okuyun. Yanlış şıklar rastgele yazılmadı; bu konuda öğrencilerin gerçekten yaptığı hatalardan seçildi. Sınav soruları da aynı yolla hazırlanır.

Madde 1. while döngüsünde koşul ne zaman sınanır?

  • A. Her yinelemeden sonra; gövde en az bir kez çalışır
  • B. Yalnızca döngüye ilk girişte
  • C. Gövdenin ortasında, güncelleme satırından hemen sonra
  • D. Her yinelemeden önce; koşul yanlışsa gövde o tur hiç çalışmaz
  • E. Program başlarken bir kez, sonra sonuç saklanır

Madde 2. Aşağıdaki program ne yazdırır?

sayac = 10

while sayac < 5:
    print(sayac)
    sayac = sayac + 1
  • A. 10
  • B. Hiçbir şey yazmaz
  • C. 10’dan 4’e kadar olan sayılar
  • D. Sonsuz döngüye girer
  • E. Hata verir; koşul başlangıçta yanlış olamaz

Madde 3. sayac = 1 ile başlayan ve while sayac < 5: koşulunu kullanan bir döngü, gövdesinde sayac birer artarken hangi sayıları yazdırır?

  • A. 1, 2, 3, 4
  • B. 1, 2, 3, 4, 5
  • C. 1, 2, 3
  • D. 0, 1, 2, 3, 4
  • E. 2, 3, 4

Madde 4. Aşağıdaki döngü neden hiç bitmez?

sayac = 1

while sayac <= 5:
    print(sayac)
  • A. Python while döngülerini en fazla beş kez çalıştırır
  • B. print() çağrısı döngüyü yavaşlattığı için
  • C. <= yerine < kullanılmalıydı
  • D. Gövdede sayac değişmediği için koşul hep doğru kalır
  • E. Başlangıç değeri 0 olmalıydı

Madde 5. Aşağıdaki döngü bittiğinde toplam değişkeninin değeri nedir?

sayi = 1
toplam = 0

while sayi <= 4:
    toplam = toplam + sayi
    sayi = sayi + 1
  • A. 15
  • B. 10
  • C. 0
  • D. 4
  • E. 5

Madde 6. off-by-one hatasının en sık nedeni nedir?

  • A. Döngü gövdesindeki girintinin yanlış olmasından
  • B. Kullanılan Python sürümünün eski olmasından
  • C. Döngü içinde fazladan print() kullanılmasından
  • D. Döngü değişkeninin adının yanlış yazılmasından
  • E. Sınırın ya da başlangıcın yanlış seçilmesinden

Madde 7. Bir program 1–10 arasındaki sayıları toplayacak ama sonuç 45 çıkıyor. En olası neden nedir?

sayi = 1
toplam = 0

while sayi < 10:
    toplam = toplam + sayi
    sayi = sayi + 1
  • A. Bu sonuç doğrudur; 1–10 toplamı zaten 45’tir
  • B. sayi iki kez artırılıyor
  • C. Başlangıç değeri 0 olmalıydı
  • D. toplam yanlış yerde güncelleniyor
  • E. Koşul 10’u dışarıda bırakıyor; < yerine <= gerekir

Madde 8. Sayaç ile biriktirici arasındaki fark nedir?

  • A. İkisi de aynıdır; yalnızca değişken adları farklıdır
  • B. Biriktirici yalnızca for döngüsünde kullanılabilir
  • C. Sayaç birer artar, biriktiriciye her turda bir değer eklenir
  • D. Sayaç int, biriktirici her zaman float olmak zorundadır
  • E. Sayaç döngü dışında, biriktirici döngü içinde tanımlanır

Madde 1. Doğru: D. Koşul başta sınandığı için döngü gövdesi sıfır kez de çalışabilir.

  • A yanlış: Bu, bazı dillerdeki do-while davranışıdır. Python’ın while yapısı koşulu başta sınar.
  • B yanlış: Koşul her turun başında yeniden sınanır; yoksa döngü hiç bitmezdi.
  • C yanlış: Koşul gövdenin içinde değil, başında yer alır.
  • E yanlış: Sonuç saklanmaz; değişkenler değiştikçe koşul yeniden değerlendirilir.

Madde 2. Doğru: B. Koşul daha ilk sınamada yanlıştır (10 < 5); gövde hiç çalışmaz.

  • A yanlış: Koşul gövdeden önce sınanır; bu yüzden gövde bir kez bile çalışmaz.
  • C yanlış: Sayaç azalmıyor, artıyor; üstelik 10 daha başta koşulu sağlamıyor.
  • D yanlış: Koşul hiç sağlanmadığı için döngü daha başlamadan biter.
  • E yanlış: Koşulun başta yanlış olması geçerli bir durumdur; döngü sıfır kez çalışır.

Madde 3. Doğru: A. Sınır 5 koşula dâhil değildir; döngü 4’ten sonra biter.

  • B yanlış: 5 < 5 yanlıştır; 5 hiç yazdırılmaz. Bu koşulda <= kullanılsaydı yazılırdı.
  • C yanlış: 4 < 5 doğru olduğu için 4 de yazılır.
  • D yanlış: Başlangıç 1; 0 hiç yazdırılmaz.
  • E yanlış: İlk tur sayac 1 iken çalışır ve 1 yazılır.

Madde 4. Doğru: D. Döngünün bitmesi koşulu yanlışa çevirecek bir güncellemeye bağlıdır; burada öyle bir satır yok.

  • A yanlış: Böyle bir sınır yoktur; döngü koşul yanlış olana kadar sürer.
  • B yanlış: Sorun hız değil; döngü yavaş değil, hiç bitmiyor.
  • C yanlış: < yazılsa da döngü bitmez; sayac yine hiç değişmez.
  • E yanlış: Başlangıcı değiştirmek de güncelleme eksikliğini gidermez.

Madde 5. Doğru: B. 1 + 2 + 3 + 4 toplamı 10’dur; döngü sayi 5 olunca durur.

  • A yanlış: 5 hiç eklenmez; sayi 5 olduğunda koşul yanlıştır ve gövde çalışmaz.
  • C yanlış: Döngü dört kez çalışır ve her turda toplam büyür.
  • D yanlış: toplama her turda yeni sayı eklenir; yalnızca son sayıyı tutmaz.
  • E yanlış: Bu, döngü bittiğinde sayi değişkeninin değeridir; sorulan toplam.

Madde 6. Doğru: E. Off-by-one, döngünün bir tur eksik ya da bir tur fazla çalışmasıdır. Arkasında neredeyse her zaman iki karardan biri vardır: sınırın koşula dâhil edilip edilmeyeceği (< mı <= mi) ya da sayacın hangi değerden başlayacağı.

  • A yanlış: Girinti döngünün neyi tekrarladığını belirlediği için tur sayısını da etkiliyor gibi görünür. Ama girinti hatası hangi satırın bloğa ait olduğunu değiştirir; bu ayrı bir hata türüdür.
  • B yanlış: Beklenmedik bir sonuçta araçtan şüphelenmek yaygındır. Ama sürümle ilgisi yoktur; hata programcının sınır kararındadır.
  • C yanlış: Fazladan satırlar ekranda göründüğü için sorun print()te aranabilir. Ama print() yalnızca gösterir; yineleme sayısını etkilemez.
  • D yanlış: Yanlış yazılan ad da sık yapılan bir yazım kusuru olduğu için akla gelir. Ama yanlış ad NameError verir; hata vermeden fazladan bir tur çalıştırmaz.

Madde 7. Doğru: E. 1’den 9’a kadarki toplam 45’tir. Beklenen 55 için 10 da toplama girmelidir.

  • A yanlış: 1’den 10’a kadar toplam 55’tir.
  • B yanlış: Kodda tek bir artırma var.
  • C yanlış: 0 eklemek toplamı değiştirmez; sonuç yine 45 kalır.
  • D yanlış: Güncelleme sırası burada sonucu değiştirmez; her turda sayi eklenir.

Madde 8. Doğru: C. Sayaç bir şeyin kaç kez olduğunu tutar. Biriktirici her turda eklenen değerlerle biriken sonucu tutar. Kaç öğrencinin geçtiğini sayaç, puanların toplamını biriktirici tutar.

  • A yanlış: İkisi de döngüden önce başlatılıp döngüde += ile güncellendiği için aynı görünür. Ama ne tuttukları farklıdır; sayaç kaç kez olduğunu sayar, biriktirici değer biriktirir.
  • B yanlış: Toplama örnekleri çoğu zaman for ile gösterildiği için akla gelir. Ama biriktirici iki döngü türünde de kullanılabilir.
  • D yanlış: Ortalama gibi örneklerde biriken sonuç ondalıklı çıktığı için akla gelir. Ama tür bir ölçüt değil; biriktirici de tam sayı tutabilir.
  • E yanlış: Biriktiricinin değeri döngüde oluştuğu için orada tanımlandığı sanılabilir. Ama ikisi de döngüden önce başlatılır ve döngü içinde güncellenir; döngünün içinde başlatılan biriktirici her turda sıfırlanır.

Tek sayfa özet

Bu hafta bir işi, koşul doğru olduğu sürece while ile tekrarladık.

  • while koşulu her yinelemeden önce kontrol edilir.
  • Koşul başlangıçta False ise gövde hiç çalışmaz.
  • Sayaç, döngünün kaçıncı adımda olduğunu izlemek için kullanılabilir.
  • Başlangıç değeri, devam koşulu ve güncelleme birlikte düşünülmelidir.
  • Döngü koşulunu değiştirecek bir güncelleme yoksa sonsuz döngü oluşabilir; kendi bilgisayarınızda durmayan programı Ctrl+C ile kesebilirsiniz.
  • off-by-one hataları çoğunlukla sınırın koşula dâhil edilip edilmemesinden ya da yanlış başlangıç değerinden kaynaklanır.
  • Kod izleme tablosunda her yinelemede değişkenlerin nasıl değiştiği görülür.
  • Döngüde sayacın yanında birikim ya da toplam gibi biriktiriciler ve başka değişkenler de güncellenebilir.
  • Geçerli girdi gelene kadar sorma kalıbında input() satırı iki kez yazılıyor; break öğrendikten sonra bu tekrarı kaldıracağız.

Bir sonraki bölümde, kaç kez tekrar edileceği baştan belli olan işler için for ve range() kullanacağız. Sayaç, biriktirici, arama ve sayma gibi döngü kalıplarını da orada çalışacağız.

Bu bölümün kazanımları

Bu bölümü bitiren öğrenci:

  • while koşulunun her yinelemeden önce sınandığını gösterir.
  • Başlangıç değeri, devam koşulu ve güncellemeyi birlikte kurar.
  • Güncellemesi eksik ya da yanlış yönde olan döngünün hiç bitmeyeceğini tanır.
  • Kod izleme tablosuyla her yinelemedeki değişken değerlerini takip eder.
  • Sınırın koşula dâhil edilip edilmemesinden doğan off-by-one hatasını açıklar.
  • Sayaç ile biriktiriciyi birbirinden ayırır.
Back to top