De functie zip() is ontstaan in Python 2 (toen gaf deze een lijst terug), en sinds Python 3 geeft het een lazy iterator terug. Het "naait" verschillende sequenties samen in tuples element voor element, wat het werken met parallelle iterabele collecties handig en efficiënt heeft gemaakt.
Vaak is het nodig om meerdere lijsten (of andere soorten sequenties) tegelijkertijd te verwerken — bijvoorbeeld om door een paar sleutel-waarde te lopen of om coördinaten punt-paar te verwerken. Het zelfstandig synchroniseren van indexen is een bron van fouten en onleesbaarheid van de code, vooral voor collecties van verschillende lengtes.
De functie zip() accepteert een willekeurig aantal iterabele objecten en retourneert een iterator van tuples, waarin de overeenkomende elementen van elk iterabel zijn genomen. Als de sequenties van verschillende lengtes zijn, stopt het resultaat bij de kortste.
names = ['Alice', 'Bob', 'Charlie'] ages = [24, 27, 30] for name, age in zip(names, ages): print(f'{name} is {age} years old')
Zip kan worden uitgebreid met behulp van *:
pairs = [(1, 'a'), (2, 'b'), (3, 'c')] nums, chars = zip(*pairs) print(nums) # (1, 2, 3) print(chars) # ('a', 'b', 'c')
Wat gebeurt er als je zip() sequenties van verschillende lengtes doorgeeft?
zip() stopt wanneer het het einde van de kortste collectie bereikt — de overige elementen van de langere collecties worden genegeerd.
print(list(zip([1,2,3], ['a','b']))) # [(1, 'a'), (2, 'b')]
Hoe krijg je tuples door kortere sequenties aan te vullen met een standaardwaarde?
Standaard zip() kan dit niet, maar er is itertools.zip_longest voor dit gedrag:
from itertools import zip_longest for a, b in zip_longest([1,2], ['x','y','z'], fillvalue=None): print(a, b) # 1 x # 2 y # None z
Kun je het resultaat van zip() "uitpakken" om de oorspronkelijke lijsten weer te krijgen?
Ja, als alle oorspronkelijke collecties dezelfde lengte hadden en het resultaat niet was gewijzigd, kan de *-operator zip uitbreiden.
pairs = [(1,2), (3,4)] a, b = zip(*pairs) print(a) # (1, 3) print(b) # (2, 4)
Het verwerken van gerelateerde collecties van verschillende lengtes, zonder rekening te houden met de kenmerken van zip:
lst1 = [1,2,3,4] lst2 = ['a','b'] for x, y in zip(lst1, lst2): print(x, y) # 1 a # 2 b # (3,4) en 'c', 'd' van lst1 zijn niet verwerkt
Voordelen:
Nadelen:
Gebruik zip_longest met fillvalue om ervoor te zorgen dat geen enkel element verloren gaat:
from itertools import zip_longest lst1 = [1,2,3,4] lst2 = ['a','b'] for x, y in zip_longest(lst1, lst2, fillvalue='?'): print(x, y) # 1 a # 2 b # 3 ? # 4 ?
Voordelen:
Nadelen: