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 ya da birikim hedefe ulaşana kadar her hafta para eklemek bu türden işlerdir. Aynı adımları tekrar tekrar çalıştıran yapıya döngü denir. 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 sayfadaki kod hücreleri kendiliğinden çalışmaz. Her hücrede önce çıktıyı tahmin edin, sonra Run Code düğmesine basın. Kodu değiştirip yeniden çalıştırabilir, Start Over ile ilk hâline döndürebilirsiniz.
Bu bölümün kapsamı
whilekoş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-onehatası - Sayaç ile biriktiricinin ayrımı
- Döngülerin çalışma süresi ve hız karşılaştırması
- Çalışan programı
Ctrl+Cile kesme (derste kullanılır, sınavda sorulmaz) whileile birlikte kullanılanelsebloğu
Bu başlıklar konunun devamıdır. İleride karşınıza çıkar, ama bu derste ezberlemeniz beklenmiyor.
Koşu turlarını nasıl sayardınız?
Okulun koşu pistinde bir tur 400 metre. Beden eğitimi öğretmeni her öğrenciye 2000 metre koşturuyor. Öğrenci bir turu bitirince öğretmen iki şey not ediyor: toplam mesafeye 400 ekliyor ve tur sayısını bir artırıyor. Öğrenci 2000 metreyi tamamlayınca duruyor. Öğretmen de kaç tur attığını ve kaç metre koştuğunu söylüyor.
Öğretmenin yerine pistin kenarındaki bir sensör sayacak. Sensörün programı yalnız ona yazdığınız kuralları bilecek. Ne zaman sayacağını, neyi sayacağını ve ne zaman duracağını kendi başına bulmayacak. Öğretmenin işini 1. bölümdeki sözde kodla, Türkçe ve madde madde yazın. Sonra kurallarınızı dört durumla deneyin:
- Sayım sıfırdan başladı. Öğrenci durduğunda kurallarınız kaç tur ve kaç metre söylüyor?
- Sensör sabahki sayımı sıfırlamayı unuttu, sayım
2000metreden başladı. Kurallarınıza göre öğrenci kaç tur daha koşar? - Pist yenilendi, bir tur artık
300metre. Kurallarınıza göre öğrenci kaç tur koşar, durduğunda kaç metre koşmuş olur? - Sensör turları algılamıyor, toplam mesafe hiç artmıyor. Kurallarınıza göre öğrenci ne zaman durur?
Python bilmeniz gerekmiyor: “Her turdan sonra toplama 400 ekle” de bir kural. Kurallarınızı bir kenara yazın. Bölümde her birinin Python’da nasıl yazıldığını göreceğiz. Alıştırmalardan önce listenize döneceğiz.
while: koşul doğru olduğu sürece tekrar et
En basit hâli aşağıdaki hücrede. while satırının altındaki girintili bloğa döngünün gövdesi denir. Hücre kaç satır yazar, son satır ne olur?
Programın çalışma sırası:
sayac <= 3koşulu kontrol edilir.- Koşul
Trueise döngü gövdesi çalışır. sayacbir artırılır.- Program yeniden
whilesatırına döner. - Koşul
Falseolduğunda döngü biter.
Gövde sayac 1, 2 ve 3 iken çalışır ve bu üç değeri alt alta yazar. sayac 4 olunca 4 <= 3 yanlıştır ve döngü biter.
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 kod hangi satırları yazar? Önce tahmin edin, sonra çalıştırın.
Yalnızca kaç satır yazdırıldığını saymayın. Her yinelemede şu üç şeye bakın:
- Döngü başındaki
sayacdeğeri - Koşulun sonucu
- Gövdenin sonunda
sayacın aldığı yeni değer
Döngü gövdesi sayac değerleri 2, 4 ve 6 iken çalışır. sayac 8 olduğunda koşul False olur ve döngü biter. print("Bitti") döngünün dışında olduğu için en sonda bir kez çalışır.
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.
Aşağıdaki programı izleyelim. Çalıştırmadan önce tablonun boş hücrelerini kendiniz doldurun ve print(toplam) satırının ne yazacağını bulun.
| Yineleme | Döngü başında sayac |
toplam sonrası |
Gövde sonunda sayac |
|---|---|---|---|
| 1 | 1 | 1 | 2 |
| 2 | ? | ? | ? |
| 3 | ? | ? | ? |
| 4 | ? | ? | ? |
| 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ü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 tutan değişkendir. Döngünün bir gün durması şu satıra bağlıdır:
sayac = sayac + 1Bu satır olmasaydı sayac sürekli 1 kalır ve sayac <= 3 koşulu hep True olurdu. Koşulu hiçbir zaman False olmayan döngüye sonsuz döngü denir.
İ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 + 1Bu sayfadaki hücreler en çok 5 saniye çalışır, sonra durdurulur. 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 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.
Güncelleme olduğu hâlde döngü bitmeyebilir. Aşağıdaki hücrede sayac her turda 2 artıyor. Bitti yazılır mı?
sayac 1, 3, 5, 7, 9, 11 diye ilerler ve hiçbir zaman tam 10 olmaz. sayac != 10 koşulu hep True kalır, Bitti yazılmaz. Hücre 5 saniye sonra durdurulur.
Koşul bir değere tam eşitliği bekliyorsa ve güncelleme o değerin üstünden atlıyorsa döngü durmaz. Bu yüzden durma koşulunda != yerine çoğu zaman < ya da <= yazılır: while sayac < 10:.
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.
Aşağıdaki hücre 1’den 5’e kadar sayıları yazdırmak için yazıldı. Bu işi yapıyor mu?
Hücre 1, 2, 3, 4 yazar. sayac 5 olunca 5 < 5 yanlıştır ve 5 yazılmaz. 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 - 1Baş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. Aşağıdaki hücre 1–5 aralığını yazdırmak için yazıldı. İlk satırda ne yazılır, kaç satır çıkar?
Hücre 0’dan 5’e kadar altı satır yazar. Koşul doğru: 5 de yazılıyor. Fazladan yazılan 0 başlangıç değerinden geliyor. sayac = 1 ile başlamak gerekir.
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:
- En fazla
5deneme olacak biçimde değiştirin. - İlk satırda
Deneme: 0yazdıracak bir başlangıç değeri verin. Kaç satır yazdırıldığına bakın. - Koşulu
< 3yapın. Kaç deneme yazdırılacağını tahmin edin. - 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. Hücre kaç satır yazar, son Birikim: değeri kaç olur?
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
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.
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.
Bu hafta girdinin int() ile dönüştürülebilen bir sayı olduğunu varsayıyoruz. "abc" gibi sayıya çevrilemeyen bir girdi ValueError verir. Bu hatayı yakalamayı 13. bölümde göreceğiz.
Soruya dönelim: koşu turları Python’da
Bölümün başında koşu sayımının kurallarını yazıp dört durumla denemiştiniz. Python’daki karşılıkları şöyle:
| Durum | Sözde kodda | Python’da | Dikkat |
|---|---|---|---|
| Sayım sıfırdan başladı: kaç tur, kaç metre? | “Toplam 2000 olana kadar tur at. Her turda toplama 400 ekle, tur sayısını bir artır.” | mesafe = 0, tur = 0, while mesafe < 2000: ve gövdede mesafe = mesafe + 400, tur = tur + 1 |
tur bir sayaç, mesafe bir biriktirici. Doğru sonuç 5 tur, 2000 metre. “2000’i geçene kadar koş” yazdıysanız koşul mesafe <= 2000 olur ve öğrenci bir tur fazla koşar: off-by-one |
Sayım 2000’den başladı |
“Önce bir tur koş, sonra toplama bak” | while koşulu her yinelemeden önce sınanır: 2000 < 2000 yanlış, gövde hiç çalışmaz |
Kuralınız önce koşturup sonra bakıyorsa öğrenci gereksiz bir tur atar. Python’ın while’ı önce bakar |
Tur 300 metre |
“Toplam tam 2000 olunca dur” | while mesafe != 2000: hiç durmaz. while mesafe < 2000: 7 turda, 2100 metrede durur |
300’ün katları 1800’den 2100’e atlar, hiçbiri tam 2000 olmaz. Eşitliğe bakan koşul sınırın üstünden atlayan değeri kaçırır |
| Sensör turu algılamıyor | Kural yok | Gövdede mesafe = mesafe + 400 satırı yoksa mesafe hep 0 kalır ve döngü hiç bitmez |
Koşulu bir gün False yapacak güncelleme gövdede olmalı |
300 metrelik pistteki sonucu kod izleme tablosuyla tur tur bulabilirsiniz:
| Yineleme | Başta mesafe |
mesafe < 2000 |
Sonra mesafe |
tur |
|---|---|---|---|---|
| 1 | 0 | True |
300 | 1 |
| 2 | 300 | True |
600 | 2 |
| 3 | 600 | True |
900 | 3 |
| 4 | 900 | True |
1200 | 4 |
| 5 | 1200 | True |
1500 | 5 |
| 6 | 1500 | True |
1800 | 6 |
| 7 | 1800 | True |
2100 | 7 |
Sekizinci kontrolde 2100 < 2000 yanlıştır ve döngü biter.
Listenizi tabloyla karşılaştırın. Kurallarınız öğrenciyi ne zaman durduruyor: toplam 2000’e ulaşınca mı, 2000’i geçince mi, tam 2000 olunca mı? Toplam mesafeyi hangi adımın artırdığını yazmadıysanız program da bilmez: yazmadığınız güncellemeyi kendisi eklemez.
Üret: koşu sayacını yazın
Bölümün başındaki koşu sayımını koda çevirin. Program mesafe hedef’e ulaşana kadar her turda mesafe’ye tur_uzunlugu kadar eklemeli ve tur’u 1 artırmalı.
Kabul kriterleri:
- Döngü
mesafe < hedefolduğu sürece çalışmalı. - Her yinelemede
mesafetur_uzunlugukadar,tur1artmalı. - Programı üç durumla deneyin: verilen değerlerle
5tur ve2000metre,tur_uzunlugu = 300ile7tur ve2100metre,mesafe = 2000ile başlayınca0tur.
Döngü while mesafe < hedef: satırıyla başlar. Gövdede iki ayrı değişkeni güncelleyin: biri biriktirici, biri sayaç.
hedef = 2000
tur_uzunlugu = 400
mesafe = 0
tur = 0
while mesafe < hedef:
mesafe = mesafe + tur_uzunlugu
tur = tur + 1
print("Tur:", tur)
print("Mesafe:", mesafe)Tek sayfa özet
Bu hafta bir işi, koşul doğru olduğu sürece while ile tekrarladık.
whilekoşulu her yinelemeden önce kontrol edilir.- Koşul başlangıçta
Falseise gövde hiç çalışmaz. - 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+Cile kesebilirsiniz. - Güncelleme olsa da koşul tam eşitliği bekliyorsa (
!=) ve değer sınırın üstünden atlıyorsa döngü durmaz. Durma koşulunda<ya da<=daha güvenlidir. off-by-onehataları çoğunlukla sınırın koşula dâhil edilip edilmemesinden ya da yanlış başlangıç değerinden çıkar.- Kod izleme tablosunda her yinelemede değişkenlerin nasıl değiştiği görülür.
- Sayaç kaç tur döndüğünü tutar. Biriktirici her turda eklenen değerlerle biriken sonucu tutar: koşu sayımında
tursayaç,mesafebiriktiricidir. - 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:
whilekoş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-onehatasını açıklar. - Sayaç ile biriktiriciyi birbirinden ayırt eder.