Was ist das Problem mit redu ()?

71

Es scheint im Internet eine Menge hitziger Diskussionen über die Änderungen an der Funktion redu () in Python 3.0 zu geben und darüber, wie sie entfernt werden sollten. Ich habe ein wenig Schwierigkeiten zu verstehen, warum dies der Fall ist. Ich finde es durchaus vernünftig, es in verschiedenen Fällen zu verwenden. Wenn die Verachtung einfach subjektiv wäre, kann ich mir nicht vorstellen, dass sich so viele Menschen darum kümmern würden.

Was vermisse ich? Was ist das Problem mit redu ()?

Jeremy
quelle

Antworten:

75

Wie Guido in seinem Beitrag Das Schicksal von redu () in Python 3000 sagt :

Reduzieren Sie jetzt (). Dies ist eigentlich die, die ich immer am meisten gehasst habe, denn abgesehen von einigen Beispielen mit + oder * muss ich fast jedes Mal, wenn ich einen redu () - Aufruf mit einem nicht trivialen Funktionsargument sehe, Stift und Papier greifen Diagramm, was tatsächlich in diese Funktion eingespeist wird, bevor ich verstehe, was das redu () tun soll. Meiner Meinung nach ist die Anwendbarkeit von redu () weitgehend auf assoziative Operatoren beschränkt, und in allen anderen Fällen ist es besser, die Akkumulationsschleife explizit zu schreiben.

Es gibt ein hervorragendes Beispiel für eine Verwirrung reduceim HOWTO- Artikel zur funktionalen Programmierung :

Schnell, was macht der folgende Code?

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

Sie können es herausfinden, aber es braucht Zeit, um den Ausdruck zu entwirren, um herauszufinden, was los ist. Die Verwendung einer kurzen verschachtelten def-Anweisung macht die Dinge ein bisschen besser:

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

total = reduce(combine, items)[1]

Aber es wäre am besten, wenn ich einfach eine for-Schleife verwendet hätte:

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

Oder die eingebaute Summe () und ein Generatorausdruck:

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

Viele Verwendungen von redu () sind klarer, wenn sie wie für Schleifen geschrieben werden.

DzinX
quelle
4
In diesem Fall könnte es noch einfacher sein: Summe (b für a, b in Elementen)
John Millikin
28
Der Reduktionscode entspricht nicht der for-Schleife. Hier ist das Äquivalent: total = reduce(lambda total, (a,b): total + b, items, 0)
Nathan Shively-Sanders
4
"Die Reduzierungsfunktion kann die Absicht des Codes verschleiern. Daher sollte Reduzieren aus der Sprache entfernt werden." Zugegeben, ich weiß nicht, dass jemand genau das sagt, aber es ist keine Folge.
Tony
2
Punkt genommen, aber um fair zu sein, ein Lambda in Ihr Beispiel zu werfen, ist das Äquivalent dazu, einem Mann in der Polizeiaufstellung ein blutbeflecktes Hemd zu geben. Ich werde nicht argumentieren, dass redu () zunächst nicht verwirrend ist, aber alles in functools ist, wenn Sie anfangen. Ich finde functools immer nützlicher, wenn ich lerne, sie zu benutzen. Wenn Sie Beispiele für Verwirrung wünschen, lesen Sie itertools (). Ich lerne sie auch zu lieben, war aber ein hartes erstes Date. :-)
JS.
4
Das Argument lautet "Bewegen wir uns, reduceweil damit unklarer Code geschrieben werden kann." Nun, so kann **, +und -. Sollen wir sie umziehen functools?
Eric Duminil
35

reduce()wird nicht entfernt - es wird einfach in das functoolsModul verschoben . Guidos Argumentation ist, dass mit Ausnahme von trivialen Fällen wie Summierung der mit geschriebene Code reduce()normalerweise klarer ist, wenn er als Akkumulationsschleife geschrieben wird.

John Millikin
quelle
34
Gah, das ist eine schreckliche Argumentation :(
TraumaPony
23
Ist es? Ein Großteil von Pythons Philosophie besteht darin, Code zu schreiben, der klar und offensichtlich ist. Bei einem typischen Aufruf von redu () muss ich normalerweise einen Stift ausbrechen und grafisch darstellen, mit was die Funktion aufgerufen wird.
John Millikin
31
Sofern Sie mir keine signifikante Leistungssteigerung zeigen können (mindestens 2x), werde ich jeden Tag "klar und offensichtlich" gegenüber "Kompaktheit des Ausdrucks" nehmen.
Kevin Little
9

Die Leute befürchten, dass dies einen verschleierten Programmierstil fördert und etwas tut, das mit klareren Methoden erreicht werden kann.

Ich bin nicht dagegen, mich zu reduzieren, ich finde es manchmal auch ein nützliches Werkzeug.

Eli Bendersky
quelle
3

Der Hauptgrund für die Existenz von Reduce besteht darin, das explizite Schreiben für Schleifen mit Akkumulatoren zu vermeiden. Obwohl Python über einige Funktionen zur Unterstützung des Funktionsstils verfügt, wird dies nicht empfohlen. Wenn Sie den "echten" und nicht den "pythonischen" Funktionsstil mögen, verwenden Sie stattdessen ein modernes Lisp (Clojure?) Oder Haskel.

Terminus
quelle
-1

Die Verwendung von reduzieren zur Berechnung des Werts eines Polynoms mit der Horner-Methode ist sowohl kompakt als auch ausdrucksstark.

Berechnen Sie den Polynomwert bei x. a ist ein Array von Koeffizienten für das Polynom

def poynomialValue(a,x):
   return reduce(lambda value, coef: value*x + coef, a)
user1153980
quelle
Dies versucht nicht wirklich, die Frage des OP zu beantworten. "Warum ist reduceein Problem?" Antwort: "Hier ist ein Anwendungsfall für reduce".
ShadowRanger
Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klarstellung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag. - Aus dem Rückblick
Arya McCarthy
Ein leistungsfähiges Sprachwerkzeug kann immer verwendet werden, um Kürze zu schaffen, aber es fehlt an Klarheit. Ich wollte ein Beispiel geben, in dem Reduce verwendet werden kann, um einen Algorithmus kompakt auszudrücken. Beachten Sie, dass dies ein Beispiel für einen Operator ist, der nicht assoziativ ist.
user1153980