Kiedy lepiej używać zip
zamiast itertools.izip
?
python-2.7
python-2.x
itertools
Neil G.
źródło
źródło
zip
, zbyt oczywistym, ale wciąż wartym podkreślenia, jest to, żeizip
powraca, przeziterator
który można przejść tylko raz. tj. wii = izip(a,b) ; f(ii) ; g(ii)
tym przypadku[]
przekazywana jest pusta listag
.zip
funkcja Pythona 3 to Python 2izip
. W ogóle Python 3 zmienił większość funkcji do użycia iteratorów, jak zakres, filtr, funkcji DICT, etcOdpowiedzi:
Kiedy wiesz, że będziesz potrzebować pełnej listy skonstruowanych elementów (na przykład do przekazania funkcji, która zmodyfikuje tę listę w miejscu). Lub gdy chcesz zmusić argumenty, do których przechodzisz,
zip()
aby zostały całkowicie ocenione w tym konkretnym momencie.źródło
izip
używa ponownie tylkotuple
wtedy, gdytuple
został wydany przed rozpoczęciem następnej iteracji, więc nic Cię nie zyskuje. To powiedziawszy, każda strata jest również trywialna, więc zgadzam się, że nie ma powodu, aby nie używaćizip
wyłącznie, pakując,list
jeśli potrzebujeszlist
; rzeczywiście można to zrobić na „właściwą” drogę przez dodaniefrom future_builtins import zip
do kodu PY2, co sprawia, że zwykłyzip
INTOizip
(przygotowanie do Py3 przejścia).zip
oblicza całą listę naraz,izip
oblicza elementy tylko na żądanie.Jedną ważną różnicą jest to, że „zip” zwraca rzeczywistą listę, „izip” zwraca „obiekt izip”, który nie jest listą i nie obsługuje funkcji specyficznych dla listy (takich jak indeksowanie):
>>> l1 = [1, 2, 3, 4, 5, 6] >>> l2 = [2, 3, 4, 5, 6, 7] >>> z = zip(l1, l2) >>> iz = izip(l1, l2) >>> isinstance(zip(l1, l2), list) True >>> isinstance(izip(l1, l2), list) False >>> z[::2] #Get odd places [(1, 2), (3, 4), (5, 6)] >>> iz[::2] #Same with izip Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'itertools.izip' object is unsubscriptable
Tak więc, jeśli potrzebujesz listy (obiektu nie podobnego do listy), po prostu użyj „zip”.
Poza tym „izip” może być przydatny do zapisywania pamięci lub cykli.
Np. Poniższy kod może zakończyć się po kilku cyklach, więc nie ma potrzeby obliczania wszystkich pozycji połączonej listy:
lst_a = ... #list with very large number of items lst_b = ... #list with very large number of items #At each cycle, the next couple is provided for a, b in izip(lst_a, lst_b): if a == b: break print a
użycie
zip
spowodowałoby obliczenie wszystkich(a, b)
par przed wejściem do cyklu.Ponadto, jeśli
lst_a
ilst_b
są bardzo duże (np. Miliony rekordów),zip(a, b)
zbuduje trzecią listę z podwójną spacją.Ale jeśli masz małe listy, może
zip
jest szybsze.źródło
Biblioteka itertools zapewnia „iteratory” dla typowych funkcji Pythona. Z dokumentacji itertools: „Podobnie jak zip (), z tą różnicą, że zwraca iterator zamiast listy”. I w izip () oznacza „iterator”.
Iteratory Pythona są sekwencjami „ładowanymi z opóźnieniem”, które oszczędzają pamięć na zwykłej liście w pamięci. Tak więc możesz użyć itertools.izip (a, b), gdy dwa wejścia a, b są zbyt duże, aby przechowywać je w pamięci jednocześnie.
Sprawdź koncepcje Pythona związane z wydajnym przetwarzaniem sekwencyjnym:
"generators" & "yield" "iterators" "lazy loading"
źródło
W wersji 2.x, gdy potrzebujesz listy zamiast iteratora.
źródło
itertools.izip()
z wyjątkiem sytuacji, gdy zyski byłyby czysto statystyczne.lst = zip(lst_a, lst_b)
pozwalalst[1]
lublen(lst)
. Jednakilst = itertools.izip(lst_a, lst_n)
nie uda ci się to zrobićilst[1]
lublen(ilst)
.