2015-11-18 3 views
6

Ich begann vor kurzem, funktionale Programmierung zu lernen, und kam mit diesem Beispiel auf, als ich versuchte, meinen Quizdurchschnitt für eine Klasse zu berechnen.Wann würdest du reduce() anstelle von sum() verwenden?

Das Beispiel kam ich mit ist:

scores = [90, 91, 92, 94, 95, 96, 97, 99, 100] 

def add(num1, num2): 
    '''returns the sum of the parameters''' 
    return num1 + num2 

import operator 

timeit reduce(add, scores)/len(scores) #--> 1000000 loops, best of 3: 799 ns per loop 

timeit sum(scores)/len(scores) #--> 1000000 loops, best of 3: 207 ns per loop 

timeit reduce(operator.add, scores)/len(scores) #--> 1000000 loops, best of 3: 485 ns per loop 

Es wäre, dass im obigen Beispiel scheinen, eine Funktion höherer Ordnung mit fast 4-mal langsamer.

Also meine Fragen ist, wann wäre eine gute Zeit, um eine Funktion höherer Ordnung zu verwenden, weil das obige Beispiel eindeutig nicht ist?

+0

Was ist mit der Verwendung von 'operator.add' anstelle einer benutzerdefinierten Funktion? Außerdem zwei Punkte: 1. 'sum' kann besser lesbar aussehen, je nachdem, was der Code tut (in Ihrem Fall); 2. [Guido mag nicht "reduzieren"] (http://www.artima.com/weblogs/viewpost.jsp?thread=98196) – fjarri

+0

@repzero was meinst du mit Funktionsdetails? –

+0

@fjarri hinzugefügt Fall mit operator.add, Summe ist noch schneller. Und ich stimme zu, dass die Summe in den meisten Fällen besser lesbar ist, aber ich frage mich, ob die Funktion höherer Ordnung irgendwelche Leistungsvorteile oder andere Arten von Vorteilen bringen könnte. –

Antwort

4

reduce() macht Sinn, wenn Sie einen beliebigen Betrieb über eine Liste von Daten erforderlich ist, nicht, wenn Sie bereits eine stark optimierte Bibliotheksfunktion haben, die nicht nur reduce() auf kleine Listen übertreffen, aber drastisch outperform es auf größeren .

reduce() gibt Ihnen die Flexibilität, um beliebige Falten zu erstellen, aber diese Flexibilität geht zu Lasten einiger Performance Overhead, vor allem in einer Sprache, in der die meisten grundlegenden funktionalen Konstrukte etwas außerhalb des Mainstream betrachtet werden.

Python ist "funktional", weil es erstklassige Funktionen hat, aber es ist nicht primär eine funktionale Sprache. Es bietet eine üppige Auswahl an Iteratoren für die Verwendung in Schleifen und verfügt über alle Sprachfunktionen, die das Schreiben von expliziten Schleifen erleichtern, sich jedoch nicht auf rekursiv definierte Listenoperationen konzentrieren (obwohl sie diese in begrenztem Umfang zulassen) verhindert, dass ich zum Beispiel meinen Erlang- oder Guile-Code direkt in Python paraphrasiere, aber gibt mir die Flexibilität, Dinge wie benchmark competing approaches that adhere to similar interfaces zu tun.

1

Anstelle der Summe? Noch nie.

Aber eine Reduzierung Call wäre der Weg zu gehen, wenn durch eine benutzerdefinierte Methode aggregieren.

Zum Beispiel product könnte definiert werden als:

product = lambda iterable: reduce(operator.mul, iterable) 

sum Auch

+0

Was passiert, wenn der Typ, den Sie hinzufügen, langsam hinzugefügt wird und Sie einen Zusatz vermeiden möchten? –

0

reduce in C implementiert und sum sehr verschiedene Dinge tun. Betrachten Sie eine Frage wie: „Ich eine verschachtelte Wörterbuch haben ...

d = {'foo': {'bar': {'baz': 'qux'}}} 

, und ich möchte den Wert mit einer Liste von Schlüsseln zugeordnet bekommen: ['foo', 'bar', 'baz']“. Diese konnte Forderung nach einem reduce (wenn Sie eine funktionale Programmierung Art von Person,):

>>> reduce(lambda subdict, k: subdict[k], ['foo', 'bar', 'baz'], d) 
'qux' 

Hinweis, können Sie dies nicht mit sum. Es passiert einfach, dass die Summierung ein einfaches Beispiel ist, um zu zeigen, was mit reduce passiert (da Sie es mit Klammern schreiben können und die meisten Programmierer mit der mathematischen Operationen in Klammern vertraut sind).

2

die Leistungsprobleme einstellen beiseite, ich habe folgendes zu sagen: es ist nichts falsch an allen mit sum() verwenden und stilistisch sollte wählen sum() über reduce()!reduce() ist generischer und kann daher verwendet werden, um andere Reduktionen als nur Summierung zu schreiben. sum() ist eine Reduktion, die häufig genug ist, dass es einen eigenen Namen und eine eigene Definition verdient.

Wenn Sie sich funktionale Programmiersprachen ansehen, finden Sie zum Beispiel, dass sie große Bibliotheken von allgemeinen Dienstprogrammfunktionen zum Arbeiten mit Sequenzen haben, wie Haskells Data.List oder Schemes SRFI-1. Ein Los der Funktionen in diesen Bibliotheken könnte in Bezug auf andere geschrieben werden; beispielsweise wird die map Funktion in Haskell könnte in Bezug auf foldr geschrieben (die reduce() ähnlich ist):

map :: (a -> b) -> [a] -> [b] 
map f = foldr go [] 
    where f a bs = f a : bs 

Aber niemand behauptet, dass foldr dadurch map unnötig oder etwas zu vermeiden macht. Vielmehr werden die allgemeineren Operationen wie foldr oder reduce() als Bausteine ​​ angesehen, um speziellere Funktionen zu konstruieren, die das Schreiben und Verstehen von Programmen erleichtern.

reduce() und sum() sind in der gleichen Beziehung. reduce() ist ein Baustein, den Sie erreichen, wenn Sie keine Funktion wie sum() bereits haben.

Verwandte Themen