2008-10-08 17 views
58

Wydaje się, że w Internecie jest dużo gorącej dyskusji na temat zmian funkcji reduce() w Pythonie 3.0 i sposobu jej usunięcia. Mam trudności z zrozumieniem, dlaczego tak się dzieje; Uważam, że rozsądne jest używanie go w różnych przypadkach. Jeśli pogarda była po prostu subiektywna, nie mogę sobie wyobrazić, że tak duża liczba ludzi by się tym przejmowała.Jaki jest problem z funkcją reduce()?

Czego mi brakuje? Jaki jest problem z funkcją reduce()?

Odpowiedz

62

Guido mówi w swoim The fate of reduce() in Python 3000 postu:

Więc teraz zmniejszyć(). To jest właściwie ta, której zawsze najbardziej nienawidziłem, ponieważ oprócz kilku przykładów z + lub * prawie za każdym razem, gdy widzę wywołanie funkcji reduce() z nietrywialnym argumentem funkcji, muszę pobrać pióro i papier do diagram, który jest faktycznie wprowadzany do tej funkcji, zanim zrozumiem, co ma zrobić funkcja reduce(). Moim zdaniem zastosowanie metody reduce() jest w dużym stopniu ograniczone do operatorów asocjacyjnych, a we wszystkich innych przypadkach lepiej jest jawnie zapisać pętlę akumulacji.

Jest doskonałym przykładem mylące reduce w artykule Functional Programming HOWTO:

Szybkie, co się następujący kod robi?

total = reduce(lambda a, b: (0, a[1] + b[1]), items)[1] 

Można zrozumieć to, ale na to potrzeba czasu, aby oddzielić wyrażenie dowiedzieć się co się dzieje. Korzystanie z krótkim zagnieżdżone def sprawozdań sprawia, że ​​rzeczy trochę lepiej:

def combine (a, b): 
    return 0, a[1] + b[1] 

total = reduce(combine, items)[1] 

Ale najlepiej byłoby wszystkim, gdybym po prostu stosować pętli for:

total = 0 
for a, b in items: 
    total += b 

lub suma() wbudowane w i wyrażenie generatora:

total = sum(b for a,b in items) 

Wiele zastosowań funkcji reduce() jest bardziej przejrzystych w przypadku zapisu jak w przypadku pętli.

+4

W takim przypadku może być jeszcze łatwiej: suma (b za a, b w pozycjach) –

+0

@John Millikin: Nice! :-) – DzinX

+0

Ah, przerażające - teraz, gdy patrzę w link, linia sum() jest bezpośrednio twoim cytatem. Musiał po prostu tęsknić za pierwszym razem. –

8

Ludzie martwią się, zachęcają do zaciemnionego stylu programowania, robiąc coś, co można osiągnąć dzięki bardziej przejrzystym metodom.

Nie jestem przeciwnikiem zmniejszania się, czasami uważam to za przydatne narzędzie.

31

reduce() nie jest usuwany - jest po prostu przenoszony do modułu functools. Rozumowanie Guido jest takie, że poza przypadkami trywialnymi, takimi jak sumowanie, kod napisany przy użyciu reduce() jest zwykle bardziej przejrzysty, gdy jest zapisywany jako pętla akumulacji.

+24

Gah, to okropne rozumowanie :( – TraumaPony

+16

Czy to prawda? Wiele z filozofii Pythona dotyczy pisania jasnego i oczywistego kodu: Typowe wezwanie do zmniejszania() zazwyczaj wymaga ode mnie wyrwania ołówka i wykreślenia, czym jest funkcja wywołany z. –

+23

Jeśli nie możesz pokazać mi * znacznego * zwiększenia wydajności (przynajmniej 2x), przyjmę "wyraźny i oczywisty" ponad "zwartość wypowiedzi" każdego dnia. –

1

Głównym powodem istnienia redusu jest unikanie pisanie jawnie dla pętli z akumulatorami. Mimo, że Python ma pewne cechy wspierające styl funkcjonalny, nie jest to zalecane. Jeśli podoba ci się "prawdziwy", a nie "pytonowy" styl funkcjonalny - użyj zamiast tego nowoczesnego Lispa (Clojure?) Lub Haskela.