Kiedy należy używać wyrażeń generatora, a kiedy używać wyrażeń list w Pythonie?
# Generator expression
(x*2 for x in range(256))
# List comprehension
[x*2 for x in range(256)]
python
list-comprehension
generator
Tylko czytać
źródło
źródło
[exp for x in iter]
być po prostu cukierlist((exp for x in iter))
? czy jest różnica w wykonaniu?X = [x**2 for x in range(5)]; print x
zY = list(y**2 for y in range(5)); print y
, drugi da błąd. W Python3 rozumienie listy jest rzeczywiście składniowym cukrem dla wyrażenia generatora dostarczanegolist()
zgodnie z oczekiwaniami, więc zmienna pętli nie będzie już wyciekać .Odpowiedzi:
Odpowiedź Johna jest dobra (ta lista jest lepsza, gdy chcesz powtórzyć coś wiele razy). Warto jednak zauważyć, że powinieneś użyć listy, jeśli chcesz użyć dowolnej z metod listy. Na przykład następujący kod nie będzie działać:
Zasadniczo użyj wyrażenia generatora, jeśli wszystko, co robisz, to iteracja raz. Jeśli chcesz przechowywać wygenerowane wyniki i korzystać z nich, prawdopodobnie lepiej jest zapoznać się z listą.
Ponieważ wydajność jest najczęstszym powodem wyboru jednego spośród drugiego, radzę nie martwić się o to i po prostu wybrać jedno; jeśli okaże się, że twój program działa zbyt wolno, wtedy i tylko wtedy powinieneś wrócić i martwić się o dostrojenie kodu.
źródło
a = [1, 2, 3] b = [4, 5, 6] a.extend(b)
- a będzie teraz [1, 2, 3, 4, 5, 6]. (Czy możesz dodawać nowe wiersze w komentarzach?)a = (x for x in range(0,10)), b = [1,2,3]
na przykład.a.extend(b)
zgłasza wyjątek.b.extend(a)
oceni wszystko, w którym to przypadku nie ma sensu tworzyć generatora.Iteracja wyrażeniem generatora lub zrozumieniem listy zrobi to samo. Jednak zrozumienie listy utworzy najpierw całą listę w pamięci, podczas gdy wyrażenie generatora utworzy elementy w locie, dzięki czemu będziesz mógł używać jej do bardzo dużych (a także nieskończonych!) Sekwencji.
źródło
itertools.count(n)
jest nieskończoną sekwencją liczb całkowitych, zaczynającą się od n, więc(2 ** item for item in itertools.count(n))
byłaby nieskończoną sekwencją mocy2
rozpoczynających się od2 ** n
.Używaj wyrażeń z listy, gdy wynik musi być wielokrotnie powtarzany lub gdy szybkość jest najważniejsza. Używaj wyrażeń generatora, gdy zakres jest duży lub nieskończony.
Aby uzyskać więcej informacji, zobacz Wyrażenia generatora i opisy list .
źródło
lists
są szybsze niżgenerator
wyrażenia? Po przeczytaniu odpowiedzi dF okazało się, że jest na odwrót.Ważną kwestią jest to, że analiza listy tworzy nową listę. Generator tworzy iterowalny obiekt, który „filtruje” materiał źródłowy „w locie”, gdy zużywasz bity.
Wyobraź sobie, że masz plik dziennika o wielkości 2 TB o nazwie „ogromny_plik.txt” i potrzebujesz zawartości i długości wszystkich wierszy rozpoczynających się od słowa „WEJŚCIE”.
Więc zacznij od napisania listy ze zrozumieniem:
Spowalnia to cały plik, przetwarza każdą linię i przechowuje pasujące linie w tablicy. Ta tablica może zatem zawierać do 2 TB treści. To dużo pamięci RAM i prawdopodobnie nie jest praktyczne dla twoich celów.
Zamiast tego możemy użyć generatora, aby zastosować „filtr” do naszych treści. Żadne dane nie są odczytywane, dopóki nie zaczniemy iteracji nad wynikiem.
Nawet żaden wiersz nie został jeszcze odczytany z naszego pliku. Powiedzmy, że chcemy jeszcze bardziej filtrować nasz wynik:
Wciąż nic nie zostało przeczytane, ale określiliśmy teraz dwa generatory, które będą działały na naszych danych, jak chcemy.
Wypiszmy nasze przefiltrowane linie do innego pliku:
Teraz czytamy plik wejściowy. Ponieważ nasza
for
pętla nadal żąda dodatkowych linii,long_entries
generator żąda linii odentry_lines
generatora, zwracając tylko te, których długość jest większa niż 80 znaków. Z koleientry_lines
generator żąda wierszy (filtrowanych jak wskazano) zlogfile
iteratora, który z kolei odczytuje plik.Dlatego zamiast „wypychać” dane do funkcji wyjściowej w postaci w pełni wypełnionej listy, dajesz funkcji wyjściowej sposób „wyciągania” danych tylko wtedy, gdy jest to potrzebne. W naszym przypadku jest to o wiele bardziej wydajne, ale nie tak elastyczne. Generatory są jednokierunkowe, jedno przejście; dane z odczytanego pliku dziennika są natychmiast odrzucane, więc nie możemy wrócić do poprzedniej linii. Z drugiej strony nie musimy martwić się o przechowywanie danych, gdy skończymy.
źródło
Zaletą wyrażenia generatora jest to, że zużywa mniej pamięci, ponieważ nie buduje całej listy jednocześnie. Wyrażeń generatora najlepiej używać, gdy lista jest pośrednikiem, takim jak sumowanie wyników lub tworzenie dykta z wyników.
Na przykład:
Zaletą jest to, że lista nie jest w pełni generowana, a zatem używana jest niewielka pamięć (i powinna być również szybsza)
Powinieneś jednak używać wyrażeń listowych, gdy pożądanym produktem końcowym jest lista. Nie będziesz zapisywać żadnych pamięci za pomocą wyrażeń generatora, ponieważ chcesz wygenerowaną listę. Korzyścią jest także możliwość korzystania z dowolnej z funkcji listy, takich jak sortowanie lub odwracanie.
Na przykład:
źródło
sum(x*2 for x in xrange(256))
sorted
ireversed
działa dobrze na dowolnych iterowalnych wyrażeniach generatora.Podczas tworzenia generatora ze zmiennego obiektu (takiego jak lista) należy pamiętać, że generator zostanie oceniony na podstawie stanu listy w momencie korzystania z generatora, a nie w momencie tworzenia generatora:
Jeśli istnieje szansa, że twoja lista zostanie zmodyfikowana (lub zmienny obiekt na tej liście), ale potrzebujesz stanu przy tworzeniu generatora, musisz zamiast tego użyć interpretacji listy.
źródło
Czasami możesz uciec od funkcji tee z itertools , zwraca ona wiele iteratorów dla tego samego generatora, z których można korzystać niezależnie.
źródło
Używam modułu Hadoop Mincemeat . Myślę, że to świetny przykład na zanotowanie:
Tutaj generator pobiera liczby z pliku tekstowego (nawet 15 GB) i stosuje prostą matematykę na tych liczbach, korzystając z funkcji zmniejszania map przez Hadoop. Gdybym nie użył funkcji plonu, ale zamiast zrozumienia listy, obliczenie sum i średniej zajęłoby znacznie więcej czasu (nie wspominając o złożoności przestrzeni).
Hadoop jest doskonałym przykładem wykorzystania wszystkich zalet generatorów.
źródło