Bir iterable, döngü yapabileceğiniz herhangi bir şeydir (liste, string, dict); bir iterator, gerçek iterasyonu yapan, tek seferde değerler üreten ve konumunu izleyen nesnedir. Bu ayrım Python'da for döngülerinin nasıl çalıştığını temel alır.
İki protokol
Iterable → has __iter__() → returns an iterator
Iterator → has __next__() → returns the next value (and __iter__ returning itself)
Bir for döngüsü gerçekte nasıl çalışır
# this for loop...
for x in [1, 2, 3]:
print(x)
# ...is roughly equivalent to:
it = iter([1, 2, 3]) # __iter__ → get an iterator from the iterable
while True:
try:
x = next(it) # __next__ → get the next value
print(x)
except StopIteration: # raised when exhausted → loop ends
break
Bir for döngüsü, iterator almak için iter() çağırır, ardından StopIteration sonu işaret edene kadar tekrar tekrar next() çağırır. Bu protokol, herhangi bir iterable'ı döngü yapılabilir hale getirir.
Pratikde Iterable vs iterator
nums = [1, 2, 3] # an ITERABLE (a list)
it = iter(nums) # an ITERATOR over it
next(it) # 1
next(it) # 2
next(it) # 3
next(it) # StopIteration
# the list is REUSABLE (get a fresh iterator each loop);
# an iterator is CONSUMED ONCE — exhausted after one pass
list(it) # [] — already used up
Temel fark: bir iterable (liste) birçok kez döngü yapılabilir (her for yeni bir iterator alır); bir iterator tek kullanımlık — bir kez tükenirse boş kalır.
Özel bir iterator oluşturma
class Countdown:
def __init__(self, start): self.n = start
def __iter__(self): return self # the iterable returns itself as iterator
def __next__(self):
if self.n <= 0:
raise StopIteration # signal the end
self.n -= 1
return self.n + 1
for x in Countdown(3): # 3, 2, 1
print(x)
Generatorlar iteratorlardır
def gen(): yield 1; yield 2 # a generator function returns an iterator automatically
Generatorlar iteratorlar oluşturmanın kolay yoludur — yield, __next__/StopIteration mekanizmasını sizin için yönetir.
Neden önemli
Iterable/iterator ayrımı, Python'da for döngülerinin nasıl çalıştığını açıklar ve iterasyon protokolü aracılığıyla tüm koleksiyonlar (listeler, dictler, dosyalar, generatorlar) genelinde iterasyonun nasıl birleştirildiğini gösterir.
Bunu anlamak gerçek davranışları açıklığa kavuşturur — bir iterator'ün neden sadece bir kez tüketilebileceğini (yaygın hata: bir generator/zip'i iki kez döngü yapmak ikinci seferde hiçbir şey vermez), generatorlar'ın neden iteratorlar olduğunu ve kendi nesnelerinizi iterable yapmanızı sağlar.
Bu protokol Python'un zarif, tutarlı iterasyon modelinin temelini oluşturur ve generatorlar, tembel değerlendirme ve özel iterable sınıflarıyla çalışmak için gereklidir.
