Historia pytania
Funkcja zip() pojawiła się w Pythonie jako wygodny sposób na "zszywanie" kilku sekwencji w krotki z odpowiadającymi elementami, uzyskując swoistą "macierzową" strukturę.
Problem
Błąd występuje, gdy programiści stosują zip dla sekwencji o różnej długości, oczekując, że wynik będzie według najdłuższej, lub niewłaściwie używają rozpakowywania przy odwracaniu konwersji.
Rozwiązanie
zip() przyjmuje jedną lub więcej sekwencji, zwracając iterator krotek, gdzie krotka n zawiera n-te elementy ze wszystkich sekwencji. Iteracja kończy się, gdy najkrótsza sekwencja się wyczerpuje.
Przykład kodu:
names = ['John', 'Anna', 'Peter'] ages = [28, 22, 35] grouped = list(zip(names, ages)) print(grouped) # [('John', 28), ('Anna', 22), ('Peter', 35)]
Kluczowe cechy:
Co się stanie, jeśli przekażemy zip sekwencjom o różnej długości?
Wynik będzie długości najkrótszej sekwencji. Pozostałe elementy zostaną zignorowane.
zip([1,2,3], ['a','b']) # [(1,'a'), (2,'b')]
Czy można "rozwinąć" zip? Jak odzyskać oryginalne sekwencje?
Tak, za pomocą znaku zapytania-rozpakowywania i zip(*iterator):
pairs = [(1, "a"), (2, "b")] numbers, letters = zip(*pairs) print(numbers) # (1, 2)
Jakie są różnice między zip a itertools.zip_longest?
zip_longest z itertools działa do najdłuższej sekwencji, wypełniając luki określonym fillvalue.
from itertools import zip_longest zip_longest([1,2], ['a','b','c'], fillvalue=None) # [(1,'a'), (2,'b'), (None, 'c')]
Przetwarzaliśmy pary użytkowników i haseł przez zip, ale listy okazały się różnej długości. Kilku użytkowników nie zostało uwzględnionych z powodu działania zip według krótszej listy.
Zalety:
Wady:
Do połączenia wyników testu i imion studentów zastosowano zip_longest z fillvalue="n/a", zachowując dane wszystkich uczestników.
Zalety:
Wady: