← Kursa Dön
📄 Text · 15 min

for Döngüsü ve range()

Hayatında hiç aynı işi 100 kere tekrarlamak zorunda kaldın mı? Belki bir listedeki her öğrenciye aynı mesajı göndermek, belki bir tablodaki her satırı kontrol etmek... İşte for döngüsü tam olarak bunu otomatikleştiren yapı. Python'un for döngüsü diğer dillerden biraz farklı — sayaç tabanlı değil, iterasyon tabanlı. Yani bir koleksiyondaki her öğeyi sırayla ziyaret eder.

Bir konveyör bant analojisi düşün: Fabrikada bir konveyör bandın var ve üzerinde ürünler geçiyor. Sen bandın başında duruyorsun ve her ürüne aynı işlemi uyguluyorsun — etiket yapıştırıyorsun diyelim. for döngüsü tam olarak bu: iterable (konveyör bant) üzerindeki her item'a (ürün) aynı işlemi uygular.


Temel Söz Dizimi

meyveler = ["elma", "armut", "muz", "çilek"]

for meyve in meyveler:
    print(f"Ben {meyve} seviyorum!")

Çıktı:

Ben elma seviyorum!
Ben armut seviyorum!
Ben muz seviyorum!
Ben çilek seviyorum!

Yapı çok basit:

  • for anahtar kelimesi

  • Döngü değişkeni (meyve) — her turda sıradaki öğeyi alır

  • in anahtar kelimesi

  • Iterable (üzerinde döngü kurulabilecek nesne)

  • : ve girintili kod bloğu

Python'da for döngüsü her tür iterable üzerinde çalışır: liste, tuple, string, dictionary, set, range, dosya satırları, generator...

# String üzerinde — her karakter bir iterasyon
for harf in "Python":
    print(harf, end=" ")  # P y t h o n

print()

# Tuple üzerinde
for sayi in (10, 20, 30):
    print(sayi)

# Set üzerinde (sıra garanti değil!)
for renk in {"kırmızı", "mavi", "yeşil"}:
    print(renk)

Döngü değişkeninin ismi tamamen sana kalmış. Ama anlamlı isimler ver: for s in ogrenciler yerine for ogrenci in ogrenciler yaz. Kod okuyan kişi (gelecekteki sen dahil) teşekkür edecek.


range(): Sayı Dizileri Oluşturma

range() fonksiyonu belirli bir aralıkta sayı dizisi üretir. Özellikle "N kere tekrarla" senaryolarında kullanılır.

Tek Parametre: range(stop)

# 0'dan 4'e kadar (5 dahil DEĞİL)
for i in range(5):
    print(i, end=" ")  # 0 1 2 3 4

range(5) → 0, 1, 2, 3, 4 üretir. Dikkat: 5 dahil değil! Matematikteki [0, 5) aralığı gibi — sol dahil, sağ hariç. Bu tasarım kararının mantığı var: range(5) tam olarak 5 eleman üretir (0, 1, 2, 3, 4) ve len(range(5)) == 5. İndeksleme de 0'dan başladığı için mükemmel uyum sağlar.

İki Parametre: range(start, stop)

# 3'ten 7'ye kadar (8 hariç)
for i in range(3, 8):
    print(i, end=" ")  # 3 4 5 6 7

Üç Parametre: range(start, stop, step)

# 0'dan 20'ye 3'er atlayarak
for i in range(0, 21, 3):
    print(i, end=" ")  # 0 3 6 9 12 15 18

print()

# Geriye doğru sayma
for i in range(10, 0, -1):
    print(i, end=" ")  # 10 9 8 7 6 5 4 3 2 1

print()

# Çift sayılar
for i in range(0, 20, 2):
    print(i, end=" ")  # 0 2 4 6 8 10 12 14 16 18

range() ile Üyelik Testi

range nesnesi in operatörünü destekler ve bu O(1) zaman karmaşıklığındadır — tüm elemanları kontrol etmez, matematiksel olarak hesaplar:

r = range(0, 1_000_000, 3)

print(999_999 in r)  # True — anında cevap verir
print(999_998 in r)  # False — yine anında

range() Bellek Dostu

range() tüm sayıları bellekte tutmaz — her istendiğinde hesaplar. Bu yüzden range(1_000_000_000) yazmak bellekte 1 milyar sayı depolamaz, sadece başlangıç, bitiş ve adım bilgisini tutar.

import sys

# Liste: tüm elemanları bellekte tutar
liste = list(range(1000))
print(sys.getsizeof(liste))   # ~8856 byte

# Range: sadece 3 sayı tutar (start, stop, step)
r = range(1000)
print(sys.getsizeof(r))       # 48 byte!

💡 İpucu: range() bir lazy (tembel) nesne. Eğer gerçekten listeye ihtiyacın varsa list(range(10)) kullan, ama çoğu zaman for i in range(10) yeterli. Python 2'deki xrange() artık yok, çünkü Python 3'te range() zaten lazy.


enumerate(): İndeks + Değer Birlikte

Bir listedeki hem indeksi hem değeri aynı anda almak istediğinde enumerate() kullan. Bu, Python'un en sevilen yardımcı fonksiyonlarından biri.

Problemi Görelim

meyveler = ["elma", "armut", "muz"]

# ❌ C-style yaklaşım — çirkin ve hata riski yüksek
for i in range(len(meyveler)):
    print(f"{i}: {meyveler[i]}")

# ✅ Pythonic yaklaşım — temiz ve güvenli
for i, meyve in enumerate(meyveler):
    print(f"{i}: {meyve}")

İki yaklaşım da aynı sonucu verir, ama enumerate() çok daha okunabilir. range(len(...)) kalıbı Python'da genellikle "code smell" olarak kabul edilir — her gördüğünde enumerate() kullanabilir miyim diye düşün.

Başlangıç İndeksini Belirleme

# 1'den başlat (sıralama için mükemmel)
ogrenciler = ["Ahmet", "Ayşe", "Mehmet"]

for sira, isim in enumerate(ogrenciler, start=1):
    print(f"{sira}. {isim}")

Çıktı:

1. Ahmet
2. Ayşe
3. Mehmet

start parametresi sadece sayacın başlangıcını belirler — listedeki gerçek indeksleri değiştirmez.

enumerate() Ne Döndürür?

meyveler = ["elma", "armut"]

# enumerate bir iterator döndürür
e = enumerate(meyveler)
print(list(e))  # [(0, 'elma'), (1, 'armut')]

Her eleman bir (indeks, değer) tuple'ı. for döngüsünde tuple unpacking ile i, meyve olarak ayırabilirsin.

enumerate ile Koşullu İşlem

# Boş satırları bulma
satirlar = ["Merhaba", "", "Dünya", "", "", "Python"]

bos_satirlar = []
for i, satir in enumerate(satirlar, start=1):
    if not satir:
        bos_satirlar.append(i)

print(f"Boş satırlar: {bos_satirlar}")  # [2, 4, 5]

zip(): Paralel İterasyon

Birden fazla listeyi aynı anda, paralel olarak dolaşmak istediğinde zip() kullan. Bir fermuarın iki tarafını birleştirmesi gibi — iki listeyi eleman eleman eşleştirir.

isimler = ["Ahmet", "Ayşe", "Mehmet"]
notlar = [85, 92, 78]

for isim, not_ in zip(isimler, notlar):
    print(f"{isim}: {not_}")

Çıktı:

Ahmet: 85
Ayşe: 92
Mehmet: 78

Farklı Uzunlukta Listeler

a = [1, 2, 3, 4, 5]
b = ["x", "y", "z"]

# Varsayılan: kısa olana göre durur
for x, y in zip(a, b):
    print(x, y)
# 1 x
# 2 y
# 3 z  (4 ve 5 sessizce atlanır)

Bu sessiz atlama tehlikeli olabilir. Python 3.10 ile gelen strict parametresi güvenlik sağlar:

# Uzunluk eşit değilse ValueError fırlatır
try:
    for x, y in zip(a, b, strict=True):
        print(x, y)
except ValueError as e:
    print(f"Hata: {e}")

Eksikleri doldurmak istiyorsan itertools.zip_longest kullan:

from itertools import zip_longest

# Eksikleri None ile doldurur
for x, y in zip_longest(a, b, fillvalue="-"):
    print(x, y)
# 1 x
# 2 y
# 3 z
# 4 -
# 5 -

Üçten Fazla Liste

isimler = ["Ahmet", "Ayşe", "Mehmet"]
yaslar = [25, 30, 22]
sehirler = ["İstanbul", "Ankara", "İzmir"]

for isim, yas, sehir in zip(isimler, yaslar, sehirler):
    print(f"{isim} ({yas}) - {sehir}")

zip() ile Dictionary Oluşturma

anahtarlar = ["isim", "yas", "sehir"]
degerler = ["Ahmet", 25, "İstanbul"]

sozluk = dict(zip(anahtarlar, degerler))
print(sozluk)  # {'isim': 'Ahmet', 'yas': 25, 'sehir': 'İstanbul'}

zip() ile Unzip (Tersine Çevirme)

ciftler = [(1, "a"), (2, "b"), (3, "c")]

# Unzip: * operatörü ile
sayilar, harfler = zip(*ciftler)
print(sayilar)  # (1, 2, 3)
print(harfler)  # ('a', 'b', 'c')

zip(*ciftler) ifadesi zip((1, "a"), (2, "b"), (3, "c")) şeklinde açılır. Bu, zip'in kendisinin tersini yapar — satırları sütunlara çevirir (transpose).


for-else Yapısı

Bu, Python'a özel ve çoğu programcının bilmediği bir yapı. for döngüsünün sonuna else bloğu ekleyebilirsin. Bu blok, döngü `break` ile kesilmeden normal şekilde tamamlandığında çalışır.

sayilar = [2, 4, 6, 8, 10]

for sayi in sayilar:
    if sayi % 2 != 0:
        print(f"Tek sayı bulundu: {sayi}")
        break
else:
    print("Hiç tek sayı yok — hepsi çift!")

Çıktı: Hiç tek sayı yok — hepsi çift!

Eğer listede 7 olsaydı, break çalışır ve else bloğu atlanırdı.

Arama Senaryosu

for-else'in en yaygın kullanımı "bir şey ara, bulamazsan şunu yap" kalıbıdır:

kullanicilar = [
    {"isim": "Ahmet", "rol": "user"},
    {"isim": "Ayşe", "rol": "user"},
    {"isim": "Mehmet", "rol": "admin"},
]

aranan_rol = "admin"

for kullanici in kullanicilar:
    if kullanici["rol"] == aranan_rol:
        print(f"Admin bulundu: {kullanici['isim']}")
        break
else:
    print("Admin kullanıcı bulunamadı!")

else yerine bir flag değişkeni kullanmak da mümkün ama for-else daha temiz:

# ❌ Flag ile (daha uzun, daha karmaşık)
bulundu = False
for kullanici in kullanicilar:
    if kullanici["rol"] == aranan_rol:
        print(f"Admin bulundu: {kullanici['isim']}")
        bulundu = True
        break

if not bulundu:
    print("Admin kullanıcı bulunamadı!")

Boş Iterable Durumu

Dikkat: boş bir iterable üzerinde for-else kullandığında, else bloğu çalışır çünkü break hiç çağrılmamıştır:

bos_liste = []

for item in bos_liste:
    print(item)
else:
    print("Bu çalışır!")  # Evet, çalışır

⚠️ Dikkat: for-else yapısı tartışmalıdır. Bazı Python geliştiricileri onu kafa karıştırıcı bulur. Raymond Hettinger (Python core developer) bile else yerine nobreak denmeliydi demiştir. Yine de bilmekte fayda var — başkasının kodunda karşına çıkabilir.


Nested for Döngüleri

İç içe (nested) for döngüleri, özellikle iki boyutlu veri yapıları (matrisler, tablolar) ile çalışırken gereklidir.

# Çarpım tablosu
print("    ", end="")
for j in range(1, 11):
    print(f"{j:4}", end="")
print()
print("    " + "-" * 40)

for i in range(1, 11):
    print(f"{i:2} |", end="")
    for j in range(1, 11):
        print(f"{i*j:4}", end="")
    print()

Çıktı:

       1   2   3   4   5   6   7   8   9  10
    ----------------------------------------
 1 |   1   2   3   4   5   6   7   8   9  10
 2 |   2   4   6   8  10  12  14  16  18  20
 ...

Matris İşlemleri

matris = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# Tüm elemanları düz yazdır
for satir in matris:
    for eleman in satir:
        print(eleman, end=" ")
    print()

# Matris transpoze (satır ↔ sütun)
transpose = []
for j in range(len(matris[0])):
    yeni_satir = []
    for i in range(len(matris)):
        yeni_satir.append(matris[i][j])
    transpose.append(yeni_satir)

print("Transpoze:")
for satir in transpose:
    print(satir)
# [1, 4, 7]
# [2, 5, 8]
# [3, 6, 9]

Karteziyen Çarpım

İki kümenin tüm olası kombinasyonları:

renkler = ["kırmızı", "mavi"]
bedenler = ["S", "M", "L"]

# Nested for ile
kombinasyonlar = []
for renk in renkler:
    for beden in bedenler:
        kombinasyonlar.append(f"{renk}-{beden}")

print(kombinasyonlar)
# ['kırmızı-S', 'kırmızı-M', 'kırmızı-L', 'mavi-S', 'mavi-M', 'mavi-L']

Performans Uyarısı

İç içe döngüler çarpımsal karmaşıklık yaratır. Dış döngü N, iç döngü M kere dönüyorsa toplam N×M iterasyon olur.

# N=1000, M=1000 → 1,000,000 iterasyon — yavaş olabilir!
for i in range(1000):
    for j in range(1000):
        pass  # 1 milyon kez çalışır

# Üç katman: N=100, M=100, K=100 → 1,000,000 iterasyon

Üç katmandan fazla iç içe döngü genellikle kötü tasarım işareti. Fonksiyonlara bölerek veya farklı algoritmalar kullanarak sadeleştir.


Unpacking in for: Dictionary ve Tuple Döngüleri

Python'un unpacking özelliği, for döngülerinde çok kullanışlıdır.

Dictionary Üzerinde Döngü

ogrenciler = {
    "Ahmet": 85,
    "Ayşe": 92,
    "Mehmet": 78,
}

# Sadece anahtarlar (varsayılan davranış)
for isim in ogrenciler:
    print(isim)  # Ahmet, Ayşe, Mehmet

# Sadece değerler
for not_ in ogrenciler.values():
    print(not_)  # 85, 92, 78

# Anahtar + değer (en yaygın kullanım)
for isim, not_ in ogrenciler.items():
    print(f"{isim}: {not_}")

items() metodu (key, value) tuple'ları döndürür ve for döngüsünde otomatik unpack edilir.

Tuple Listesi Üzerinde Döngü

koordinatlar = [(1, 2), (3, 4), (5, 6)]

for x, y in koordinatlar:
    print(f"x={x}, y={y}")

# Üçlü tuple
ogrenci_bilgileri = [
    ("Ahmet", 25, "İstanbul"),
    ("Ayşe", 30, "Ankara"),
    ("Mehmet", 22, "İzmir"),
]

for isim, yas, sehir in ogrenci_bilgileri:
    print(f"{isim} ({yas}) - {sehir}")

Yıldızlı Unpacking (Star Unpacking)

veriler = [(1, "a", "b", "c"), (2, "d", "e", "f")]

for ilk, *geri_kalan in veriler:
    print(f"İlk: {ilk}, Geri kalan: {geri_kalan}")
# İlk: 1, Geri kalan: ['a', 'b', 'c']
# İlk: 2, Geri kalan: ['d', 'e', 'f']

*geri_kalan kalan tüm elemanları bir listeye toplar. Başa veya ortaya da koyabilirsin:

for *bas, son in veriler:
    print(f"Baş: {bas}, Son: {son}")
# Baş: [1, 'a', 'b'], Son: c
# Baş: [2, 'd', 'e'], Son: f

Pratik Örnekler

Örnek 1: FizzBuzz

Klasik programlama mülakatı sorusu — 1'den 30'a kadar say, 3'e bölünenler "Fizz", 5'e bölünenler "Buzz", ikisine birden bölünenler "FizzBuzz":

for i in range(1, 31):
    if i % 15 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)

Neden i % 15 ilk sırada? Çünkü hem 3'e hem 5'e bölünen sayılar 15'e de bölünür. Eğer i % 3 önce kontrol edilirse, 15 gibi sayılar sadece "Fizz" olarak yazılır ve "FizzBuzz" hiç görünmez.

Örnek 2: Asal Sayı Kontrolü

sayi = 29

if sayi < 2:
    print(f"{sayi} asal değil")
else:
    for i in range(2, int(sayi ** 0.5) + 1):
        if sayi % i == 0:
            print(f"{sayi} asal değil ({i}'ye bölünebilir)")
            break
    else:
        print(f"{sayi} asal!")

Burada for-else mükemmel oturuyor: döngüde bölen bulunamazsa (break çalışmazsa) sayı asaldır. Neden sayi ** 0.5'e kadar kontrol ediyoruz? Çünkü bir sayının kareköküne kadar bölen bulamazsan, daha büyük bir böleni de olmaz. Bu optimizasyon O(n)'ı O(√n)'a düşürür.

Örnek 3: Kelime Frekansı Hesaplama

metin = "python güzel python harika python en iyi dil harika güzel"
kelimeler = metin.split()

frekans = {}
for kelime in kelimeler:
    frekans[kelime] = frekans.get(kelime, 0) + 1

# Frekansa göre sıralı yazdır
for kelime, sayi in sorted(frekans.items(), key=lambda x: x[1], reverse=True):
    print(f"'{kelime}': {sayi} kez")

Çıktı:

'python': 3 kez
'güzel': 2 kez
'harika': 2 kez
'en': 1 kez
'iyi': 1 kez
'dil': 1 kez

Örnek 4: Dosya Satırlarını Okuma

# Dosya üzerinde for döngüsü — bellek dostu
with open("veri.txt", "r") as dosya:
    for satir_no, satir in enumerate(dosya, start=1):
        satir = satir.strip()
        if satir:  # Boş satırları atla
            print(f"Satır {satir_no}: {satir}")

Dosya nesnesi de bir iterable! for ile satır satır okumak, tüm dosyayı belleğe yüklemekten çok daha verimli. Gigabyte'larca büyüklükteki dosyalar bile bu şekilde işlenebilir.

Örnek 5: Piramit Desen Yazdırma

n = 5

# Piramit
for i in range(1, n + 1):
    bosluk = " " * (n - i)
    yildiz = "*" * (2 * i - 1)
    print(bosluk + yildiz)

# Kum saati
for i in range(n, 0, -1):
    bosluk = " " * (n - i)
    yildiz = "*" * (2 * i - 1)
    print(bosluk + yildiz)
for i in range(2, n + 1):
    bosluk = " " * (n - i)
    yildiz = "*" * (2 * i - 1)
    print(bosluk + yildiz)

İleri Teknikler

reversed() ile Geriye Doğru

meyveler = ["elma", "armut", "muz"]

for meyve in reversed(meyveler):
    print(meyve)
# muz, armut, elma

# String'i tersten okuma
for harf in reversed("Python"):
    print(harf, end="")  # nohtyP

reversed() orijinal listeyi değiştirmez, bir iterator döndürür.

sorted() ile Sıralı Döngü

notlar = {"Mehmet": 78, "Ahmet": 85, "Ayşe": 92}

# İsme göre sıralı (alfabetik)
for isim in sorted(notlar):
    print(f"{isim}: {notlar[isim]}")

# Nota göre sıralı (büyükten küçüğe)
for isim, not_ in sorted(notlar.items(), key=lambda x: x[1], reverse=True):
    print(f"{isim}: {not_}")
# Ayşe: 92
# Ahmet: 85
# Mehmet: 78

itertools ile Güçlü Döngüler

from itertools import product, chain, islice, cycle, repeat

# product: iç içe for yerine — Karteziyen çarpım
renkler = ["kırmızı", "mavi"]
bedenler = ["S", "M", "L"]

for renk, beden in product(renkler, bedenler):
    print(f"{renk}-{beden}")

# chain: birden fazla iterable'ı uç uca birleştir
liste1 = [1, 2, 3]
liste2 = [4, 5, 6]
liste3 = [7, 8, 9]

for item in chain(liste1, liste2, liste3):
    print(item, end=" ")  # 1 2 3 4 5 6 7 8 9

print()

# islice: sadece ilk N elemanı al (büyük/sonsuz iterable'lar için)
for i in islice(range(1_000_000), 5):
    print(i, end=" ")  # 0 1 2 3 4

print()

# cycle: sonsuz tekrar (break ile kullan!)
renkler = ["kırmızı", "yeşil", "mavi"]
for i, renk in enumerate(cycle(renkler)):
    if i >= 7:
        break
    print(f"{i}: {renk}")
# 0: kırmızı, 1: yeşil, 2: mavi, 3: kırmızı, 4: yeşil, ...

Walrus Operator (:=) ile Döngüde Hesaplama

Python 3.8'de gelen walrus operator, bir ifadeyi hem hesaplayıp hem atama yapmanı sağlar:

import random

sayilar = [random.randint(1, 100) for _ in range(20)]

# Karesini hesapla ve aynı anda kontrol et
toplam = 0
for sayi in sayilar:
    if (kare := sayi ** 2) > 500:
        print(f"{sayi}² = {kare}")
        toplam += kare

print(f"500'den büyük karelerin toplamı: {toplam}")

Burada kare := sayi ** 2 hem hesaplama yapar hem kare değişkenine atar. Bu sayede aynı hesaplamayı iki kez yapmak zorunda kalmazsın.


Performans İpuçları

1. range(len()) Yerine enumerate()

items = ["a", "b", "c"]

# ❌ Yavaş ve çirkin
for i in range(len(items)):
    print(i, items[i])

# ✅ Pythonic ve hızlı
for i, item in enumerate(items):
    print(i, item)

2. Döngü İçinde Liste Oluşturma

# ❌ Yavaş — her append'de liste büyüyebilir
sonuc = []
for i in range(10000):
    sonuc.append(i ** 2)

# ✅ Hızlı — list comprehension (B04'te detaylı göreceğiz)
sonuc = [i ** 2 for i in range(10000)]

3. Local Değişken Kullan

import math

data = range(100000)

# ❌ Her turda math modülünden sqrt aranıyor
for x in data:
    y = math.sqrt(x)

# ✅ Local değişkene ata — attribute lookup azalır
sqrt = math.sqrt
for x in data:
    y = sqrt(x)

4. String Birleştirme

kelimeler = ["Python", "çok", "güzel", "bir", "dil"]

# ❌ Her += yeni string oluşturur — O(n²)
sonuc = ""
for kelime in kelimeler:
    sonuc += kelime + " "

# ✅ join kullan — O(n)
sonuc = " ".join(kelimeler)

💡 İpucu: Mikro optimizasyonlara takılma. Önce doğru çalışan kod yaz, sonra profiler ile yavaş yerleri bul, sadece oraları optimize et. "Premature optimization is the root of all evil." — Donald Knuth


Yaygın Hatalar

1. Döngü İçinde Liste Değiştirme

sayilar = [1, 2, 3, 4, 5, 6]

# ❌ Tehlikeli — döngü sırasında listeyi değiştirme
for sayi in sayilar:
    if sayi % 2 == 0:
        sayilar.remove(sayi)

print(sayilar)  # [1, 3, 5, 6] — 6 kaldı! Çünkü indeks kayıyor.

# ✅ Güvenli — kopyası üzerinde dön
sayilar = [1, 2, 3, 4, 5, 6]
for sayi in sayilar[:]:  # [:] shallow copy
    if sayi % 2 == 0:
        sayilar.remove(sayi)

print(sayilar)  # [1, 3, 5]

# ✅ En temizi — list comprehension ile filtrele
sayilar = [s for s in sayilar if s % 2 != 0]

2. Kullanılmayan Döngü Değişkeni

# Değişkeni kullanmıyorsan _ kullan (konvansiyon)
for _ in range(5):
    print("Merhaba!")

_ Python'da "bu değişkeni kullanmayacağım" anlamına gelen bir konvansiyon. Linter'lar da bunu anlar ve "unused variable" uyarısı vermez.

3. İndeks Kullanarak Erişim (Gereksiz)

isimler = ["Ahmet", "Ayşe"]

# ❌ İndeks gereksiz — C alışkanlığı
for i in range(len(isimler)):
    print(isimler[i])

# ✅ Direkt iterate et — Pythonic
for isim in isimler:
    print(isim)

4. Global Değişkeni Döngü Değişkeni Yapma

x = 100

# Dikkat: for döngüsü x'i değiştirir!
for x in range(5):
    pass

print(x)  # 4 — artık 100 değil!

Python'da for döngüsü değişkeni, döngüden sonra da var olmaya devam eder ve son aldığı değeri tutar. Buna dikkat et, özellikle aynı isimde global değişken varsa.


Özet

  • `for item in iterable` Python'un temel döngü yapısıdır — her tür iterable üzerinde çalışır (liste, string, dict, dosya, generator...).

  • `range(start, stop, step)` sayı dizileri üretir; lazy evaluation sayesinde bellekte tüm sayıları tutmaz, sadece hesap bilgisini saklar.

  • `enumerate()` indeks + değer birlikte verir — range(len(...)) yerine her zaman bunu tercih et, hem daha okunabilir hem daha güvenli.

  • `zip()` birden fazla iterable'ı paralel dolaşır; farklı uzunluklarda varsayılan olarak kısa olana göre durur (strict=True veya zip_longest alternatifleri var).

  • `for-else` döngü break olmadan tamamlanırsa else bloğu çalışır — arama senaryolarında kullanışlı ama tartışmalı bir yapı.

  • Nested for döngüleri çarpımsal karmaşıklık yaratır (N×M); 3+ katmandan kaçın ve itertools.product gibi alternatifleri değerlendir.