Pomyśl o funkcji, którą wywołuję ze względu na jej skutki uboczne, a nie zwracanie wartości (jak drukowanie na ekranie, aktualizacja GUI, drukowanie do pliku itp.).
def fun_with_side_effects(x):
...side effects...
return y
Teraz, czy Pythonic ma używać wyrażeń listowych do wywoływania tej funkcji:
[fun_with_side_effects(x) for x in y if (...conditions...)]
Zauważ, że nigdzie nie zapisuję listy
A może powinienem nazwać tę funkcję w ten sposób:
for x in y:
if (...conditions...):
fun_with_side_effects(x)
Który jest lepszy i dlaczego?
python
list-comprehension
sinan
źródło
źródło
for ... in
on używany w obu przypadkach - co prowadzi do pytań takich jak to!Odpowiedzi:
Jest to bardzo anty-Pythonic, a każdy doświadczony Pythonista sprawi, że będziesz miał nad tym piekło. Lista pośrednia jest wyrzucana po utworzeniu i potencjalnie może być bardzo, bardzo duża, a zatem kosztowna w tworzeniu.
źródło
for
, żeby się go pozbyćif
).Nie powinieneś używać rozumienia list , ponieważ, jak powiedzieli ludzie, utworzy to dużą tymczasową listę, której nie potrzebujesz. Następujące dwie metody są równoważne:
z definicją ze
consume
strony podręcznikaitertools
:Oczywiście to drugie jest jaśniejsze i łatwiejsze do zrozumienia.
źródło
map
może nie być tak intuicyjny, jeśli wcześniej nie robiono programowania funkcjonalnego.consume = collections.deque(maxlen=0).extend
Listy składane służą do tworzenia list. I chyba faktycznie tworzenia listy, należy nie używać wyrażeń listowych.
Więc dostałbym drugą opcję, po prostu iterując po liście, a następnie wywołując funkcję, gdy mają zastosowanie warunki.
źródło
Druga jest lepsza.
Pomyśl o osobie, która musiałaby zrozumieć Twój kod. Za pierwszym razem możesz łatwo zdobyć złą karmę :)
Możesz przejść między nimi, używając filter (). Rozważmy przykład:
źródło
lambda x : x > 3
.for el in (x for x in y if x > 3):
.el
ix
może mieć to samo imię, ale może to mylić ludzi.Zależy od twojego celu.
Jeśli próbujesz wykonać jakąś operację na każdym obiekcie z listy, należy zastosować drugie podejście.
Jeśli próbujesz wygenerować listę z innej listy, możesz użyć rozumienia list.
źródło
Możesz to zrobić
ale nie jest zbyt ładna.
źródło
Używanie funkcji rozumienia list do efektów ubocznych jest brzydkie, nie-Pythoniczne, nieefektywne i nie zrobiłbym tego. Chciałbym użyć
for
pętli zamiast, ponieważfor
pętla sygnalizuje styl proceduralną, w której skutki uboczne są ważne.Jeśli jednak absolutnie nalegasz na używanie funkcji list złożonych do wywoływania skutków ubocznych, powinieneś uniknąć nieefektywności, używając zamiast tego wyrażenia generatora. Jeśli absolutnie nalegasz na ten styl, wykonaj jedną z tych dwóch czynności:
lub:
Są to wyrażenia generatora, które nie generują losowej listy, która zostaje wyrzucona. Myślę, że
all
forma jest być może nieco bardziej przejrzysta, chociaż myślę, że oba są mylące i nie powinny być używane.Myślę, że to jest brzydkie i nie zrobiłbym tego w kodzie. Ale jeśli nalegasz na implementację swoich pętli w ten sposób, tak bym to zrobił.
Wydaje mi się, że listy składane i im podobne powinny sygnalizować próbę użycia czegoś, co najmniej trochę przypominającego styl funkcjonalny. Umieszczanie rzeczy z efektami ubocznymi, które łamią to założenie, spowoduje, że ludzie będą musieli uważniej czytać twój kod i myślę, że to zła rzecz.
źródło
fun_with_side_effects
zwraca True?itertools.consume
już nie istnieje, prawdopodobnie dlatego, że używanie wyrażeń ze skutkami ubocznymi jest brzydkie.