Lazy evaluation is een belangrijke concept binnen efficiënt programmeren, waarbij waarden alleen worden berekend wanneer dat nodig is. Historisch gezien zijn alle basisdatastructuren in Python (lijsten, tuples) 'gierig': ze creëren en slaan van tevoren alle elementen op in het geheugen. Met de groei van datahoeveelheden en verwerkingsbehoeften is de vraag naar lazy computation toegenomen.
Probleem: gierige berekeningen leiden tot inefficiënt gebruik van geheugen en tijd waar resultaten stapsgewijs kunnen worden verkregen — bijvoorbeeld bij het filteren, omzetten van lange collecties of het streamen van bestanden.
Oplossing: Python heeft veel tools voor lazy computations geïntroduceerd: generators, iterators, en ook functies van de standaardbibliotheek (map, filter, zip, enumerate) en de itertools-module. Al deze tools geven geen kant-en-klare collecties terug, maar "luie" objecten die resultaten één voor één leveren.
Voorbeeldcode:
result = map(lambda x: x * x, range(100)) # zal een generator-iterator teruggeven for y in result: print(y) # waarden worden berekend tijdens de iteratie import itertools inf = itertools.count(1) for i in inf: if i > 3: break print(i) # 1, 2, 3
Belangrijke kenmerken:
Geven de functies map/filter altijd een lijst terug in Python 3?
Nee, in Python 3 geven deze functies iterators terug, niet lijsten. Om een lijst te krijgen, moet je het resultaat in list() wikkelen.
x = map(int, ['1', '2']) # <map object> list(x) # [1, 2]
Kun je de lengte van het resultaat van map krijgen zonder om te zetten naar een lijst?
Nee, een iterator weet niet van tevoren hoeveel elementen hij heeft, totdat hij ze allemaal doorloopt. Je moet het via list() berekenen, wat de lazy eigenschap tenietdoet.
Is de functie range in Python 3 gulzig of lui?
Lui: range creëert een "range object" — het "berekent" elementen op verzoek, zonder de hele volgorde op te slaan.
Een script verwerkt een enorme CSV-bestand door een lijst van alle regels te maken via list(open(f)). De server "sterft" door een tekort aan geheugen bij een groot bestand.
Voordelen:
Nadelen:
De code maakt gebruik van lazy evaluation: het doorloopt de regels van het bestand met een iterator for line in open(f) of verwerkt ze via map/filter zonder tussenliggende collecties te creëren.
Voordelen:
Nadelen: