De for-in lus in Python wordt geïmplementeerd via het iteratieprotocol, dat is gebaseerd op twee speciale methoden: __iter__() en __next__(). Wanneer de lus begint, roept Python iter(obj) aan (zoekt naar de __iter__ methode). Als er een iterator object wordt geretourneerd waarin __next__() is gedefinieerd, begint de lus deze methode aan te roepen om elk volgend element te verkrijgen.
Als het element met succes wordt geleverd, gaat de iteratie door. Wanneer er een StopIteration uitzondering wordt opgegooid, wordt de lus beëindigd.
Voorbeeld van een aangepaste iterator:
class Counter: def __init__(self, low, high): self.current = low self.high = high def __iter__(self): return self def __next__(self): if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1 for num in Counter(1, 3): print(num) # Geeft 1, 2, 3 weer
Fijngevoeligheid: Veel standaardstructuren in Python implementeren het iteratorsprotocol; je kunt jouw objecten gemakkelijk hetzelfde maken.
Kan de for-in lus met elk Python object worden gebruikt? Hoe verschilt een iterable object van een iterator?
Antwoord: Nee, de for-in lus vereist dat het object iterable is, d.w.z. dat het de methode __iter__() implementeert, die een iterator retourneert (een object met de methode __next__()). De iterator retourneert zichzelf via __iter__(), terwijl het iterable object dat niet doet.
Voorbeeld:
lst = [1, 2, 3] iterator = iter(lst) print(hasattr(lst, '__iter__')) # True print(hasattr(iterator, '__next__')) # True (iterator) print(hasattr(lst, '__next__')) # False (geen iterator)
Geschiedenis
Project: Verwerking van grote bestanden.
Probleem: In het project probeerden ze een doorloop van het bestandobject te herhalen (iteratie door de regels van een bestand) zonder expliciet een nieuw bestand te openen — en bij de tweede iteratie kregen ze geen enkele regel (de pointer stond al aan het einde van het bestand!).
Geschiedenis
Project: Integratie van hun eigen collectieklasse met het framework.
Probleem: De klasse implementeerde alleen
__getitem__, maar niet__iter__, en was niet compatibel met generators en standaardlussen (for). Hierdoor gingen externe bibliotheken kapot die een iterator verwachtten.
Geschiedenis
Project: Gebruik van map/filter op aangepaste collecties.
Probleem: De eigen lijstklasse implementeerde niet
__iter__en__next__, en bleek niet compatibel met veel standaardfuncties in Python, wat pas na integratietests aan het licht kwam en aanzienlijke herwerk vereiste.