[10, 20, 30] yazımı bir listedir: birkaç değeri sırayla tutar. Şimdilik bu kadarını bilmen yeter; ayrıntısı bir sonraki modülde, Listeler dersinde.Neden önemli?
Anadolu Market'te bir günde yüzlerce sipariş oluşur. "Her siparişin tutarını topla", "İstanbul'a gidenleri say", "stoğu 5'in altına düşen ilk ürünü bul" gibi işler aynı adımı tekrar tekrar uygulamaktır. Bilgisayarın asıl gücü de budur: tekrar. Döngü (loop) bu tekrarı sen yorulmadan yapar.
for: bir koleksiyonu baştan sona gez
for döngüsü bir koleksiyonun (liste, metin, sözlük, demet, range) her elemanını sırayla bir değişkene koyar ve bloğu çalıştırır.
siparisler = [
{"id": 1001, "sehir": "Ankara", "tutar": 900.0},
{"id": 1002, "sehir": "İzmir", "tutar": 820.0},
{"id": 1003, "sehir": "Ankara", "tutar": 930.0},
{"id": 1004, "sehir": "İstanbul", "tutar": 450.0},
]
toplam = 0 # birikim (accumulator) değişkeni
for siparis in siparisler:
toplam += siparis["tutar"]
print("Toplam ciro:", toplam)
ankara_sayisi = 0 # sayaç (counter)
for siparis in siparisler:
if siparis["sehir"] == "Ankara":
ankara_sayisi += 1
print("Ankara siparişi:", ankara_sayisi)
Bu iki kalıp, yazacağın döngülerin büyük kısmını kapsar: döngüden önce bir değişkeni başlat (0, boş liste, boş sözlük), döngü içinde güncelle, döngüden sonra kullan.
range: sayı dizisi üret
for i in range(5): # 0, 1, 2, 3, 4
print(i, end=" ")
print()
for i in range(1, 6): # 1..5
print(i, end=" ")
print()
for i in range(10, 0, -3): # 10, 7, 4, 1 (adım -3)
print(i, end=" ")
print()
print(list(range(0, 20, 5)))
range(1, 6) 6'yı üretmez. Python'daki tüm aralıklar (dilimleme dahil) "başlangıç dahil, bitiş hariç" çalışır; böylece range(len(liste)) tam olarak indeksleri verir.enumerate: elemanla birlikte sıra numarası
"Kaçıncı eleman?" sorusuna range(len(liste)) yerine enumerate ile cevap ver; hem eleman hem indeks gelir.
sehirler = ["Ankara", "İzmir", "İstanbul"]
for sira, sehir in enumerate(sehirler, start=1):
print(f"{sira}. {sehir}")
zip: paralel listeleri yan yana gez
urunler = ["Kulaklık", "Klavye", "Mouse"]
adetler = [12, 3, 25]
for urun, adet in zip(urunler, adetler):
durum = "AZ" if adet < 5 else "ok"
print(f"{urun}: {adet} ({durum})")
zip en kısa liste bitince durur. Sözlük gezerken de aynı "çift" mantığı var: for anahtar, deger in sozluk.items():.
while: koşul doğru olduğu sürece
Kaç kez döneceğini baştan bilmiyorsan while kullan. Her turdan önce koşul yeniden kontrol edilir.
bakiye = 1000
ay = 0
while bakiye > 0:
bakiye -= 350
ay += 1
print(f"{ay}. ay sonunda bakiye: {bakiye}")
print("Bakiye", ay, "ayda tükendi")
bakiye -= 350 satırını unutursan program donar. Her while yazdığında kendine sor: "Koşulu False yapacak satır hangisi ve kesin çalışıyor mu?"break, continue ve döngü else
| İfade | Ne yapar | Tipik kullanım |
|---|---|---|
break | Döngüyü hemen bitirir | Aranan bulundu, devam etmeye gerek yok |
continue | Bu turu atlar, sonraki tura geçer | İstenmeyen kaydı pas geç |
else | Döngü break ile kesilmeden biterse çalışır | "Hiçbiri eşleşmedi" mesajı |
stok = {"Kulaklık": 12, "Klavye": 3, "Mouse": 25, "Monitör": 0}
# break: ilk kritik ürünü bul
for urun, adet in stok.items():
if adet < 5:
print("İlk kritik ürün:", urun)
break
# continue: stoğu sıfır olanları atla
for urun, adet in stok.items():
if adet == 0:
continue
print(f"{urun} satışa açık ({adet})")
# else: arama sonuçsuz kaldıysa
aranan = "Webcam"
for urun in stok:
if urun == aranan:
print("Bulundu")
break
else:
print(aranan, "stok listesinde yok")
İç içe döngü
Döngü içine döngü yazabilirsin; iç döngü dış döngünün her turunda baştan sona döner. Toplam tur sayısı çarpılır (3 şehir × 4 ürün = 12 tur), bu yüzden büyük verilerde dikkatli ol.
sehirler = ["Ankara", "İzmir"]
urunler = ["Kulaklık", "Mouse"]
for sehir in sehirler:
for urun in urunler:
print(f"{sehir} - {urun}")
"En büyüğü bul" kalıbı
siparisler = [("Ayşe", 900.0), ("Mehmet", 820.0), ("Elif", 1250.0), ("Can", 450.0)]
en_yuksek_ad = None
en_yuksek_tutar = 0
for ad, tutar in siparisler:
if tutar > en_yuksek_tutar:
en_yuksek_ad, en_yuksek_tutar = ad, tutar
print(f"En yüksek sipariş: {en_yuksek_ad} ({en_yuksek_tutar} TL)")
# Aynı iş tek satırda (ileride sık kullanacaksın)
print(max(siparisler, key=lambda s: s[1]))
range'i tam tanı
range bir liste değil, sayıları istendikçe üreten hafif bir nesnedir: range(1_000_000) bellekte bir milyon sayı tutmaz. Üç parametresi vardır: başlangıç (dahil), bitiş (hariç) ve adım. Adım negatif olursa geriye sayar; bu durumda başlangıç bitişten büyük olmalıdır, yoksa hiç tur dönmez.
print(list(range(5))) # 0..4
print(list(range(2, 11, 4))) # 2, 6, 10
print(list(range(10, 0, -3))) # geri sayım: 10, 7, 4, 1
print(list(range(0, 10, -1))) # boş: yön yanlış
r = range(0, 100, 5)
print(len(r), 35 in r, r[-1]) # len, in ve indeks de çalışır
aylar = ["Oca", "Şub", "Mar", "Nis"]
for ay in reversed(aylar): # listeyi kopyalamadan tersten gez
print(ay, end=" ")
print()
1_000_000 yazımı Python 3.6'dan beri geçerlidir ve 1000000 ile aynıdır; büyük sayıları okunur kılar. Tutar sabitlerinde (LIMIT = 50_000) kullanman tavsiye edilir.enumerate ve zip'in ayrıntıları
enumerate(liste, start=1) sıra numarasını 1'den başlatır; raporlarda "1. satır" demek için idealdir. zip ise listelerden en kısası bitince durur ve uzun listedeki fazla elemanları sessizce atar. Veri hatasını gizleyen bu davranış yerine, Python 3.10'dan beri strict=True ile uzunluklar farklıysa hata alabilirsin.
urunler = ["çay", "kahve", "şeker"]
fiyatlar = [120, 340] # bir fiyat eksik!
print(list(zip(urunler, fiyatlar))) # şeker sessizce kayboldu
try:
for u, f in zip(urunler, fiyatlar, strict=True):
print(u, f)
except ValueError as h:
print("Veri hatası:", h)
for no, (u, f) in enumerate(zip(urunler, [120, 340, 45]), start=1):
print(f"{no}. {u:<6} {f:>4} TL")
Çıktıya dikkat et: strict=True farkı ancak kısa liste bittiği anda anlar; o ana kadarki turlar (çay ve kahve) zaten çalışmıştır. Veritabanına yazma gibi geri alınması zor işlemlerden önce uzunlukları baştan karşılaştırmak (if len(a) != len(b): ...) daha güvenlidir.
Dikkat: zip ve enumerate de range gibi tembeldir ama bir farkla: bir kez tüketilirler. z = zip(a, b) nesnesini bir kez gezdikten sonra ikinci gezişte boş gelir. Nedenini Yineleyiciler (iterator) ve üreteçler (generator) dersinde göreceksin; şimdilik zip'i ya doğrudan döngü başlığında kullan ya da list(zip(...)) ile listeye çevir.
İç içe döngüden çıkmak
break yalnızca içinde bulunduğu döngüyü kırar. İç döngüde aradığını bulduğunda dıştaki döngüyü de durdurmak istiyorsan üç yolun var. En temizi aramayı bir fonksiyona koyup return etmektir; return tüm döngülerden birden çıkar.
| Yöntem | Nasıl? | Ne zaman? |
|---|---|---|
| Fonksiyon + return | Bulunca return sonuc | Hemen her zaman en okunaklısı |
| Bayrak değişkeni | bulundu = True, iç break, dışta if bulundu: break | Fonksiyona ayıramıyorsan |
| for-else | İç döngü break etmezse else: continue, sonra dışta break | Kısa kodlarda; okuması zordur |
raflar = [["çay", "kahve"], ["şeker", "tuz", "un"], ["su"]]
def raf_bul(raflar, aranan):
for i, raf in enumerate(raflar):
for j, urun in enumerate(raf):
if urun == aranan:
return (i, j) # iki döngüden birden çıkar
return None
print(raf_bul(raflar, "tuz"), raf_bul(raflar, "pirinç"))
bulundu = None
for i, raf in enumerate(raflar):
for j, urun in enumerate(raf):
if urun == "tuz":
bulundu = (i, j)
break # yalnız iç döngü
if bulundu:
break # dış döngü
print(bulundu)
while True ve sınırlı deneme
Kaç tur süreceği bilinmeyen ama "şu olunca dur" dediğin döngülerde while True + break kalıbı okunaklıdır: menü döngüleri, kuyruktan iş çekme, kullanıcı doğru girene kadar sorma. Gerçek sistemlerde her zaman bir üst sınır koyarsın: ATM üç yanlış PIN'de kartı bloke eder, bir API isteği beş denemeden sonra vazgeçer.
denemeler = ["1111", "2580", "1234"] # kullanıcının sırayla girdikleri
dogru_pin = "1234"
hak = 3
deneme = 0
while True:
if deneme == hak or deneme == len(denemeler):
print("Kart bloke / deneme bitti")
break
girilen = denemeler[deneme]
deneme += 1
if girilen == dogru_pin:
print(f"Giriş başarılı ({deneme}. deneme)")
break
print("Hatalı PIN, kalan hak:", hak - deneme)
Döngüde metin biriktirme: join
Döngüde metin += parca yazmak küçük verilerde sorun değildir ama her adımda yeni bir metin oluşturur. Parçaları listede toplayıp sonunda "ayraç".join(liste) demek hem daha hızlı hem de "son elemandan sonra ayraç olmasın" derdini ortadan kaldırır. Kullanmadığın döngü değişkenine _ adını vermek de yaygın bir alışkanlıktır.
sehirler = ["İzmir", "Ankara", "Bursa"]
parcalar = []
for s in sehirler:
parcalar.append(s.upper())
print(", ".join(parcalar))
for _ in range(3):
print("-" * 10)
satirlar = []
for no, s in enumerate(sehirler, start=1):
satirlar.append(f"{no};{s}")
print("\n".join(["no;sehir"] + satirlar))
Son satırdaki \n satır sonu karakteridir; join ile CSV benzeri bir metni tek seferde oluşturduk. Döngülerin yaygın kalıplarını (sayaç, en iyi değer, komşu karşılaştırma, frekans) bir sonraki derste, Döngü kalıpları dersinde sistematik olarak çalışacaksın.
range(1, n) yazıp n'inci elemanı atlamaktır; ikincisi farklı uzunluktaki iki listeyi zip'leyip fazlalığı fark etmemektir. Ekipler bu yüzden indeksle gezmek yerine doğrudan elemanı gezer (for x in liste), paralel listeleri strict=True ile birleştirir ve her yeniden deneme döngüsüne bir üst sınır koyar.Döngü yerine yerleşik fonksiyon
Toplam için sum(), en büyük/küçük için max()/min(), "hiç var mı / hepsi mi" için any()/all() yazmak hem daha kısa hem de daha hızlıdır; bu fonksiyonlar C ile yazılmıştır. Döngüyü kalıbı anlamak için öğren; işte ise önce yerleşik fonksiyon var mı diye bak. Orta seviyede liste comprehension ile bu kalıplar tek satıra inecek.
Döngü içinde listeyi değiştirme
Üzerinde dolaştığın listeden eleman silmek elemanların atlanmasına yol açar. Ya yeni bir liste kur (kalanlar = [] ve koşula uyanları ekle) ya da kopyası üzerinde dön: for x in liste[:]:.
Sonsuz döngü bazen kasıtlıdır
Sunucular ve menü ekranları while True: ile yazılır ve içeride break ile çıkılır. Tuzak olan "sonsuz" değil, "çıkış yolu olmayan" döngüdür. Kasıtlı yazıyorsan çıkış koşulunu ilk satırlarda açıkça göster.