Kiedy lepiej używać zip
zamiast itertools.izip
?
zip
funkcja Pythona 3 to Python 2 izip
. W ogóle Python 3 zmienił większość funkcji do użycia iteratorów, jak zakres, filtr, funkcji DICT, etc
Kiedy lepiej używać zip
zamiast itertools.izip
?
zip
funkcja Pythona 3 to Python 2 izip
. W ogóle Python 3 zmienił większość funkcji do użycia iteratorów, jak zakres, filtr, funkcji DICT, etc
Odpowiedzi:
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.
izip
używa ponownie tylko tuple
wtedy, gdy tuple
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 potrzebujesz list
; rzeczywiście można to zrobić na „właściwą” drogę przez dodanie from future_builtins import zip
do kodu PY2, co sprawia, że zwykły zip
INTO izip
(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
i lst_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.
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"
W wersji 2.x, gdy potrzebujesz listy zamiast iteratora.
itertools.izip()
z wyjątkiem sytuacji, gdy zyski byłyby czysto statystyczne.
lst = zip(lst_a, lst_b)
pozwala lst[1]
lub len(lst)
. Jednak ilst = itertools.izip(lst_a, lst_n)
nie uda ci się to zrobić ilst[1]
lub len(ilst)
.
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
.