Ders 07 / 18
Döngüler
Koleksiyon üzerinde yineleme, sayaçlı ve koşullu döngüler, sonlanma güvencesi ve birikeç kalıbı.
İçindekiler
Kursun ortak problemi bir ölçüm dizisinin ortalamasını ve en büyüğünü bulmaktı. Şimdiye kadar bu, hazır işlevlerle yapıldı. Bu ders, aynı işi adım adım yapan yapıyı tanımlar: döngü.
Döngü, bir kod bloğunun birden çok kez yürütülmesini sağlar. Kaç kez yürütüleceği ya baştan bellidir ya da bir koşula bağlıdır; bu ayrım, döngü türlerini belirler.
Koleksiyon Üzerinde Yineleme
En sık kullanılan biçim, bir koleksiyonun elemanları üzerinde sırayla ilerlemektir:
olcumler = [12, 18, 7, 25, 14] for olcum in olcumler: print(olcum) # 12 / 18 / 7 / 25 / 14 (her biri ayrı satırda)
Döngü değişkeni (olcum), her turda bir sonraki elemana bağlanır. Kaç eleman varsa o
kadar tur yapılır; sayaç tutmaya, uzunluk sorgulamaya veya sınır denetimine gerek yoktur.
Bu yazımın üstünlüğü, sınır hatalarını olanaksız kılmasıdır. Elle sayaç yönetilen döngülerde en sık görülen hata, bir eleman eksik veya fazla işlemektir; koleksiyon üzerinde doğrudan yineleme bu hata sınıfını ortadan kaldırır.
Sayaçlı Döngü
Bazı problemlerde elemanın kendisi değil, sırası gerekir: ilk üç ölçümü işlemek, iki diziyi aynı anda gezmek veya belirli sayıda tekrar yapmak gibi.
for i in range(5): print(i, end=" ") print() # 0 1 2 3 4 for i in range(len(olcumler)): print(f"{i}. ölçüm: {olcumler[i]}") # 0. ölçüm: 12 ... 4. ölçüm: 14
Sayma aralığının sıfırdan başlaması ve üst sınırın dışarıda kalması yaygın bir
sözleşmedir: range(5) beş değer üretir ve son değer ’tür. Bu düzenin yararı,
range(len(dizi)) ifadesinin tam olarak geçerli dizinleri vermesidir.
Yalnızca sıra numarası gerekiyorsa sayaçlı döngü doğru araçtır. Hem sıra hem eleman gerekiyorsa, çoğu dil ikisini birlikte veren bir yapı sunar; elemanı dizinle tekrar aramak gereksiz iştir.
Koşullu Döngü
Tur sayısı önceden bilinmiyorsa koşullu döngü kullanılır. Koşul her turdan önce sınanır; sağlanmadığında döngü biter.
kalan = 100 tur = 0 while kalan > 1: kalan = kalan // 2 # her turda yarıya iner tur += 1 print(tur) # 6
Bu döngü, bir sayının kaç kez yarılanabileceğini bulur. Tur sayısı baştan bilinmez; başlangıç değerine bağlıdır. Aynı hesap, önceki kurstaki ikili arama örneğinin maliyetinin de kaynağıdır.
Koşullu döngünün bir varyantı, koşulu turun sonunda sınar; böylece gövde en az bir kez çalışır. Kullanıcıdan geçerli bir değer alınana kadar sorma kalıbı bu biçimi gerektirir.
Sonlanma Güvencesi
Döngünün duracağını garanti eden bir şey yoktur; bunu program yazan sağlar. Kural şudur: her turda, koşulu yanlışlamaya yaklaşan bir değişiklik olmalıdır.
Yukarıdaki örnekte kalan her turda küçülür ve sıfıra doğru gider; sıfır ile bir
arasındaki değerler koşulu yanlışlar. Bu azalan büyüklük, döngünün sonlanma gerekçesidir.
Gerekçe kurulamıyorsa döngü sonsuza kadar sürebilir:
kalan = 100 while kalan > 1: kalan = kalan // 2 if kalan == 3: kalan = 100 # geriye sıçrama: azalma güvencesi bozuldu
Bu döngü hiç bitmez. Program çalışır durumda kalır, işlemciyi meşgul eder ve dışarıdan durdurulmadıkça sonlanmaz. Sonsuz döngü, çalışma zamanı hatası üretmediği için ilk derste tanımlanan mantık hatası sınıfına girer.
Bilinçli sonsuz döngüler de vardır: bir sunucu, istek beklerken kasıtlı olarak durmaz. Bu durumda çıkış, döngü koşulundan değil, bir sonraki derste ele alınacak erken çıkış deyimlerinden veya dış bir sinyalden gelir.
Birikeç Kalıbı
Döngülerin en yaygın kullanımı, tur boyunca bir değeri biriktirmektir. Kalıp üç adımdan oluşur: birikeci başlat, her turda güncelle, döngüden sonra kullan.
olcumler = [12, 18, 7, 25, 14] toplam = 0 # 1. başlangıç değeri for olcum in olcumler: toplam += olcum # 2. her turda güncelle ortalama = toplam / len(olcumler) # 3. sonucu kullan print(toplam, ortalama) # 76 15.2
Başlangıç değerinin seçimi, işlemin etkisiz elemanıdır: toplama için sıfır, çarpma için birdir. Yanlış seçilen başlangıç değeri sessizce yanlış sonuç verir.
En büyük değeri bulmak da aynı kalıptır, ancak başlangıç değeri daha dikkat ister:
en_buyuk = olcumler[0] # ilk eleman başlangıç kabul edilir for olcum in olcumler: if olcum > en_buyuk: en_buyuk = olcum print(en_buyuk) # 25
Burada sıfırla başlamak yanlış olurdu: tüm ölçümler negatif olsaydı, sonuç yanlışlıkla sıfır çıkardı. Doğru başlangıç, dizinin ilk elemanıdır — ve bu, dizinin boş olmadığını varsayar. Boş girdi, bu tür kodun standart kenar durumudur ve döngüden önce ele alınmalıdır.
Kursun ortak problemi böylece hazır işlev kullanmadan çözülmüş oldu: iki döngü, iki birikeç.
Döngü Değişmezi
Sonlanma, döngü hakkındaki iki sorudan yalnızca biridir. İkincisi doğruluktur: döngü bittiğinde sonuç neden doğrudur?
Yanıt döngü değişmezi kavramıyla verilir: her turun başında ve sonunda doğru kalan
bir ifade. Birikeç döngüsünün değişmezi şudur — toplam, o ana kadar gezilen
elemanların toplamıdır.
Değişmez üç yerde sınanır. Döngüye girmeden önce doğrudur (hiç eleman gezilmemiştir,
toplam sıfırdır). Her tur onu korur (bir eleman gezilir, aynı eleman toplama eklenir).
Döngü bittiğinde ise tüm elemanlar gezilmiştir; değişmez, toplam değerinin tüm
elemanların toplamı olduğunu söyler. İstenen sonuç budur.
Bu üç adım, döngünün doğruluğunun kanıtıdır ve tek tek turları izlemeden kurulur.
En büyük değeri bulan döngünün değişmezi de aynı biçimde yazılır: en_buyuk, o ana
kadar gezilen elemanların en büyüğüdür. Bu ifadeyi yazmak, başlangıç değerinin neden
ilk eleman olması gerektiğini de açıklar — sıfırla başlanırsa değişmez, döngüye
girmeden yanlıştır.
Değişmez yazma alışkanlığı, algoritmaların doğruluk kanıtlarının temelidir ve Algoritmalar kursunda biçimselleştirilir.
İç İçe Döngüler
Bir döngünün gövdesi başka bir döngü içerebilir. Dış döngünün her turu, iç döngünün tamamını çalıştırır; toplam tur sayısı, ikisinin çarpımıdır.
for i in range(3): for j in range(2): print(i, j, end=" ") print() # 0 0 0 1 1 0 1 1 2 0 2 1
Çarpımsal büyüme, iç içe döngülerin başlıca maliyetidir: her yeni düzey, iş miktarını kat kat artırır. Bu gözlem, algoritma karmaşıklığı kavramının çıkış noktasıdır ve Algoritmalar kursunda biçimselleştirilir. Bu kurs için yeterli olan sezgi şudur: veri büyüdükçe, iç içe döngülerin maliyeti tek düzeyli döngülerden çok daha hızlı artar.
Özet
- Koleksiyon üzerinde yineleme, elemanları sırayla işler ve sınır hatalarını ortadan kaldırır.
- Sayaçlı döngü, elemanın kendisi değil sırası gerektiğinde kullanılır (sayma sıfırdan başlar, üst sınır dışarıda kalır); koşullu döngü ise tur sayısı önceden bilinmediğinde kullanılır.
- Bir döngünün sonlanması, her turda koşulu yanlışlamaya yaklaşan bir değişiklikle güvenceye alınır; bu değişiklik yoksa döngü sonsuza dek sürer.
- Birikeç kalıbı üç adımdır: başlat, her turda güncelle, sonra kullan; başlangıç değeri işlemin etkisiz elemanıdır ve en büyük değer aramada ilk elemandır.
- Döngü değişmezi, her turda doğru kalan ifadedir ve döngünün doğruluğunu turları izlemeden gerekçelendirir.
- İç içe döngülerde toplam tur sayısı çarpımsal büyür.
Sonraki Adım
Döngüler baştan sona akar, ancak bazen turun ortasında karar vermek gerekir: aranan bulunduğunda erken çıkmak veya geçersiz bir elemanı atlayıp devam etmek gibi. Sonraki ders, döngü akışını içeriden yönlendiren deyimleri ve bunların okunabilirlik üzerindeki etkisini ele alacak.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.