2012-02-28 17 views
27

Istnieje podpowiedź semi-famous article written by Guido himself, że reduce() powinien pójść drogą dodo i opuścić język. Został nawet zdegradowany z funkcji najwyższego poziomu w Pythonie 3 (instead getting stuffed in the functools module).Python alternatywa dla zmniejszenia()

Z wieloma innymi programowymi zszywkami do programowania (mapa itp.) Dostępne są wspólne, przejrzyste alternatywy. Na przykład, większość czasu map() jest lepiej napisane jako zrozumienie list.

Chciałbym wiedzieć, czy istnieje podobna "bardziej pytonowa" alternatywa dla funkcji redukcji. Mam trochę funkcjonalnego tła programistycznego (w szczególności ML), więc myślę o rozwiązaniu często reduce(), ale jeśli jest lepszy sposób na ich wykonanie (brak rozwijania wywołania skrótu do pętli for) Chciałbym wiedzieć.

+5

Cóż, zawsze możesz po prostu zrobić 'from funpartools import reduce'. –

+1

Jeśli myślenie w kategoriach 'zmniejszenia',' krotnie', 'mapa' itp. Pasuje do ciebie, nie sądzę, że powinieneś zmienić swój sposób myślenia. Jesteś już na dobrej drodze. – Irfy

+0

@NiklasB .: Wiem, że możesz go zaimportować z functools (o czym wspomniałem w moim pytaniu). –

Odpowiedz

23

Jak powiada Guido w swoim artykule, powinieneś napisać jawną pętlę, jeśli chcesz uniknąć reduce(). Można zamienić linię

result = reduce(function, iterable, start) 

przez

result = start 
for x in iterable: 
    result = function(result, x) 
+6

Należy zauważyć, że nie jest to w 100% równoważne - 'reduce()' jak zdefiniowano w bibliotece standardowej nie wymaga argumentu start. Tak więc musisz umieścić wartę wokół pętli for, aby sprawdzić, czy iteracja jest pusta, a jeśli nie, weź pierwszą pozycję jako początek i zapętlić pozostałe elementy. Nagle ten 1-wierszowy 'reduce()' wygląda jeszcze atrakcyjniej niezależnie od tego, co myśli Guido. ;) –

+1

@AdamParkin: Twój ostatni komentarz nie robi zbyt wiele sensu. Dwa fragmenty kodu są w 100% równoważne (do celów praktycznych). Możesz * wywołać 'reduce()' bez argumentu 'start', a następnie odpowiednik będzie wyglądał inaczej, ale nie potrzebujesz specjalnych iterables z pustymi literami tak, jak byś tego potrzebował, używając' reduce() ' bez 'start'. –

+1

'reduce (set.intersection, list_of_some_sets)' zmniejszyłoby się do przecięcia wszystkich zestawów zdefiniowanych w list_of_some_sets (domyślnie używa 1. elta listy jako początku). Aby rozwinąć to w pętlę, musiałbym wyodrębnić pierwszy elt (no, każdy element) użyć tego jako mojego "startu", a następnie wprowadzić pętlę iterującą nad pozostałymi elementami n-1. Jednak wyciągnięcie tego pierwszego (lub czegoś podobnego) elementu z listy byłoby ważne tylko wtedy, gdy wiesz, że lista nie jest pusta, stąd potrzeba strażnika. Spójrz na [definicja w docs] (http://docs.python.org/library/functions.html#reduce) o co mi chodzi. –

1

Co chciałbym wiedzieć, czy istnieje podobny „więcej pythonic” alternatywą dla funkcji ograniczenia.

Tak i nie. To zależy od przypadku użycia.

W połączonym artykule Guido sugeruje, że większość, ale nie wszystkie redukcje powinny być zapisane jako pętle. Istnieją ograniczone okoliczności, w których uważa on, że zastosowanie ma reduce.

Więc w moim umyśle, stosowalność zmniejszyć() jest dość znacznie ograniczona do operatorom asocjacyjnych, a we wszystkich innych przypadkach lepiej jest pisać pętlę akumulacji wyraźnie.

Nie ma zbyt wielu operatorów asocjacyjnych. (To są operatory X, dla których (a X b) X c jest równe X (b X c).) Myślę, że jest to prawie ograniczone do +, *, &, |,^i skrótu i ​​/ lub.

+0

Świetna uwaga, i zgadzam się, chociaż nie jest to tak naprawdę odpowiedź na to pytanie, ale raczej (dość dobra) wnikliwość związana z artykułem cytowanym w pytaniu. Być może byłoby to bardziej odpowiednie jako komentarz do pytania niż sugerowana odpowiedź? –

+1

@AdamParkin Fair point. Przepisany jako odpowiedź. – kkurian

+0

Przebiegłem przez twoją odpowiedź, decydując, czy powinienem użyć 'reduce' w moim kodzie. W moim przypadku ograniczam się do zestawu unikatowych wartości z bardzo bardzo dużej listy. Tak więc, o ile jest to warte, chciałbym dodać zestaw złączy w zestawie operatorów asocjacyjnych. – Rich