Ich verwende meistens Lambda-Funktionen, aber manchmal verwende ich verschachtelte Funktionen, die das gleiche Verhalten zu bieten scheinen.
Hier sind einige triviale Beispiele, bei denen sie funktional dasselbe tun, wenn sie in einer anderen Funktion gefunden wurden:
Lambda-Funktion
>>> a = lambda x : 1 + x
>>> a(5)
6
Verschachtelte Funktion
>>> def b(x): return 1 + x
>>> b(5)
6
Gibt es Vorteile gegenüber der Verwendung? (Leistung? Lesbarkeit? Einschränkungen? Konsistenz? Usw.)
Ist es überhaupt wichtig? Wenn dies nicht der Fall ist, verstößt dies gegen das pythonische Prinzip:
Es sollte einen - und vorzugsweise nur einen - offensichtlichen Weg geben, dies zu tun .
lambda
einverstanden, wann sie verwendet werden soll , aber ich bin nicht der Meinung, dass dies "sehr selten" ist, es ist üblich für Schlüsselfunktionensorted
oderitertools.groupby
usw., z. B.sorted(['a1', 'b0'], key= lambda x: int(x[1]))
In der Praxis gibt es für mich zwei Unterschiede:
Das erste ist, was sie tun und was sie zurückgeben:
def ist ein Schlüsselwort, das nichts zurückgibt und einen 'Namen' im lokalen Namespace erstellt.
Lambda ist ein Schlüsselwort, das ein Funktionsobjekt zurückgibt und keinen 'Namen' im lokalen Namespace erstellt.
Wenn Sie also eine Funktion aufrufen müssen, die ein Funktionsobjekt übernimmt, können Sie dies in einer Zeile Python-Code nur mit einem Lambda tun. Es gibt kein Äquivalent zu def.
In einigen Frameworks ist dies tatsächlich recht häufig; Zum Beispiel benutze ich Twisted oft und mache so etwas wie
ist ziemlich häufig und prägnanter mit Lambdas.
Der zweite Unterschied besteht darin, was die eigentliche Funktion tun darf.
Beispielsweise,
funktioniert wie erwartet, während
ist ein SyntaxError.
Natürlich gibt es Problemumgehungen - ersetzen Sie
print
durchsys.stdout.write
oderimport
mit__import__
. Aber normalerweise ist es in diesem Fall besser, eine Funktion zu verwenden.quelle
In diesem Interview sagt Guido van Rossum, er wünschte, er hätte "Lambda" nicht in Python gelassen:
IMHO, Iambdas können manchmal bequem sein, sind aber normalerweise auf Kosten der Lesbarkeit bequem. Können Sie mir sagen, was dies bewirkt:
Ich habe es geschrieben und es hat eine Minute gedauert, bis ich es herausgefunden habe. Dies ist von Project Euler - ich werde nicht sagen, welches Problem, weil ich Spoiler hasse, aber es läuft in 0,124 Sekunden :)
quelle
lambda
es naheliegend war, in 3.0 nicht entfernt zu werden, und dass Guido nicht darum kämpfte, es zu behalten.Für n = 1000 gibt es einige Zeitpunkte für den Aufruf einer Funktion gegen ein Lambda:
quelle
Performance:
Das Erstellen einer Funktion mit
lambda
ist etwas schneller als das Erstellen mitdef
. Der Unterschied ist aufdef
einen Namenseintrag in der Tabelle Einheimischen zu schaffen. Die resultierende Funktion hat die gleiche Ausführungsgeschwindigkeit.Lesbarkeit:
Lambda-Funktionen sind für die meisten Python-Benutzer etwas weniger lesbar, aber unter bestimmten Umständen auch viel prägnanter. Erwägen Sie die Umstellung von einer nicht funktionalen auf eine funktionale Routine:
Wie Sie sehen können, ist die
lambda
Version kürzer und "einfacher" in dem Sinne, dass Sie nurlambda v:
die ursprüngliche nicht funktionierende Version hinzufügen müssen, um sie in die funktionale Version zu konvertieren. Es ist auch viel prägnanter. Denken Sie jedoch daran, dass viele Python-Benutzer von der Lambda-Syntax verwirrt sein werden. Was Sie also an Länge und wirklicher Komplexität verlieren, kann durch Verwirrung bei anderen Programmierern zurückgewonnen werden.Einschränkungen:
lambda
Funktionen können nur einmal verwendet werden, es sei denn, sie sind einem Variablennamen zugeordnet.lambda
Funktionen, die Variablennamen zugewiesen sind, haben keinen Vorteil gegenüberdef
Funktionen.lambda
Funktionen können schwierig oder unmöglich zu beizen sein.def
Die Namen der Funktionen müssen sorgfältig ausgewählt werden, damit sie angemessen beschreibend und eindeutig sind oder zumindest anderweitig nicht verwendet werden.Konsistenz:
Python vermeidet meistens funktionale Programmierkonventionen zugunsten einer prozeduralen und einfacheren objektiven Semantik. Der
lambda
Bediener steht in direktem Kontrast zu dieser Tendenz. Darüber hinaus erweitertdef
dielambda
Funktion Ihre Syntax als Alternative zu der bereits vorherrschenden . Einige würden das für weniger konsistent halten.Bereits vorhandene Funktionen:
Wie von anderen angemerkt, können viele Anwendungen
lambda
im Feld durch Mitglieder desoperator
oder anderer Module ersetzt werden. Zum Beispiel:Die Verwendung der bereits vorhandenen Funktion kann in vielen Fällen die Lesbarkeit von Code verbessern.
Das pythonische Prinzip: „Es sollte einen - und vorzugsweise nur einen - offensichtlichen Weg geben, dies zu tun.“
Das ähnelt der einzigen Quelle der Wahrheitslehre . Leider war das Prinzip der offensichtlichen Vorgehensweise für Python immer eher ein wehmütiges Streben als ein wahres Leitprinzip. Betrachten Sie das sehr leistungsfähige Array-Verständnis in Python. Sie sind funktional äquivalent zu den
map
undfilter
Funktionen:lambda
unddef
sind die gleichen.Es ist Ansichtssache, aber ich würde sagen, dass alles in der Python-Sprache, das für den allgemeinen Gebrauch bestimmt ist und offensichtlich nichts kaputt macht, "pythonisch" genug ist.
quelle
Die Verwendung eines Lambda gegenüber einer regulären Funktion hat einen Vorteil: Sie werden in einem Ausdruck erstellt.
Es gibt mehrere Nachteile:
'<lambda>'
)Sie sind auch beide der gleiche Objekttyp. Aus diesen Gründen ziehe ich es im Allgemeinen vor, Funktionen mit dem
def
Schlüsselwort anstatt mit Lambdas zu erstellen .Erster Punkt - sie sind die gleiche Art von Objekt
Ein Lambda ergibt den gleichen Objekttyp wie eine reguläre Funktion
Da Lambdas Funktionen sind, sind sie erstklassige Objekte.
Sowohl Lambdas als auch Funktionen:
In Lambdas fehlen jedoch standardmäßig einige Dinge, die Funktionen über die vollständige Syntax der Funktionsdefinition erhalten.
Eine Lamba
__name__
ist'<lambda>'
Lambdas sind schließlich anonyme Funktionen, daher kennen sie ihren eigenen Namen nicht.
Daher können Lambdas nicht programmgesteuert in ihrem Namespace nachgeschlagen werden.
Dies schränkt bestimmte Dinge ein. Zum Beispiel
foo
kann mit serialisiertem Code nachgeschlagen werden, währendl
nicht:Wir können
foo
gut nachschlagen - weil es seinen eigenen Namen kennt:Lambdas haben keine Anmerkungen und keine Dokumentzeichenfolge
Grundsätzlich sind Lambdas nicht dokumentiert. Lassen Sie uns umschreiben
foo
, um besser dokumentiert zu werden:Jetzt hat foo Dokumentation:
Wir haben nicht den gleichen Mechanismus, um Lambdas die gleichen Informationen zu geben:
Aber wir können sie hacken:
Aber es gibt wahrscheinlich einen Fehler, der die Ausgabe der Hilfe durcheinander bringt.
Lambdas kann nur einen Ausdruck zurückgeben
Lambdas kann keine komplexen Anweisungen zurückgeben, sondern nur Ausdrücke.
Ausdrücke können zugegebenermaßen ziemlich komplex sein, und wenn Sie sich sehr anstrengen, können Sie dies wahrscheinlich auch mit einem Lambda erreichen, aber die zusätzliche Komplexität wirkt sich eher nachteilig auf das Schreiben von klarem Code aus.
Wir verwenden Python für Klarheit und Wartbarkeit. Übermäßiger Gebrauch von Lambdas kann dem entgegenwirken.
Der einzige Vorteil für Lambdas: Kann in einem einzigen Ausdruck erstellt werden
Dies ist der einzig mögliche Vorteil. Da Sie ein Lambda mit einem Ausdruck erstellen können, können Sie es innerhalb eines Funktionsaufrufs erstellen.
Durch das Erstellen einer Funktion innerhalb eines Funktionsaufrufs wird die (kostengünstige) Namenssuche im Vergleich zu einer an anderer Stelle erstellten vermieden.
Da Python jedoch streng evaluiert wird, gibt es keinen anderen Leistungsgewinn als die Vermeidung der Namenssuche.
Für einen sehr einfachen Ausdruck könnte ich ein Lambda wählen.
Ich neige auch dazu, Lambdas zu verwenden, wenn ich interaktives Python mache, um mehrere Zeilen zu vermeiden, wenn eine dies tut. Ich verwende das folgende Codeformat, wenn ich beim Aufruf ein Argument an einen Konstruktor übergeben möchte
timeit.repeat
:Und nun:
Ich glaube, der geringfügige Zeitunterschied oben kann auf die Namenssuche in zurückgeführt werden
return_nullary_function
- beachten Sie, dass er sehr vernachlässigbar ist.Fazit
Lambdas eignen sich für informelle Situationen, in denen Sie Codezeilen minimieren möchten, um einen einzelnen Punkt hervorzuheben.
Lambdas sind schlecht für formellere Situationen, in denen Sie Klarheit für Code-Redakteure benötigen, die später kommen, insbesondere in Fällen, in denen sie nicht trivial sind.
Wir wissen, dass wir unseren Objekten gute Namen geben sollen. Wie können wir das tun, wenn das Objekt keinen Namen hat?
Aus all diesen Gründen ziehe ich es im Allgemeinen vor, Funktionen mit
def
statt mit zu erstellenlambda
.quelle
Ich stimme dem Rat von nosklo zu: Wenn Sie der Funktion einen Namen geben müssen, verwenden Sie
def
. Ich reservierelambda
Funktionen für Fälle, in denen ich nur einen kurzen Codeausschnitt an eine andere Funktion übergebe, z.quelle
Obwohl es mit den anderen Antworten übereinstimmt, ist es manchmal besser lesbar. Hier ist ein Beispiel
lambda
, das sich als nützlich erweist. In einem Anwendungsfall stoße ich immer wieder auf eine N-Dimensiondefaultdict
.Hier ist ein Beispiel:
Ich finde es lesbarer als ein
def
für die zweite Dimension zu erstellen . Dies ist für höhere Dimensionen noch wichtiger.quelle
from functools import partial; defaultdict(partial(defaultdict, list))
. Weisen Sie den Teil einem Namen zu, wenn Sie ihn mehrmals verwenden möchten. Wenn Sie jedoch weiterhin auf dieses Konstrukt stoßen, bedeutet dies, dass Sie nicht trocken sind. Berücksichtigen Sie es in einer Utility-Bibliothek. Sie können dieses Konstrukt verwenden, um ein beliebiges n-dimensionales Standarddikt mit anderen Funktionswerkzeugen (oder einer Schleife oder Rekursion) zu erstellen.Lambda wurde hauptsächlich für einfache Rückruffunktionen und für Map, Reduce, Filter verwendet, für die eine Funktion als Argument erforderlich ist. Mit Listenverständnis zur Norm und dem Hinzufügen erlaubt, wenn wie in:
Es ist kaum vorstellbar, dass Lambda im täglichen Gebrauch wirklich verwendet wird. Daher würde ich sagen, vermeiden Sie Lambda und erstellen Sie verschachtelte Funktionen.
quelle
Eine wichtige Einschränkung von Lambdas ist, dass sie nichts anderes als einen Ausdruck enthalten können. Es ist fast unmöglich, dass ein Lambda-Ausdruck etwas anderes als triviale Nebenwirkungen hervorruft, da er keinen annähernd so reichen Körper haben kann wie eine
def
ed-Funktion.Davon abgesehen hat Lua meinen Programmierstil dahingehend beeinflusst, dass anonyme Funktionen in großem Umfang verwendet werden, und ich habe meinen Code damit verschmutzt. Darüber hinaus neige ich dazu, Map / Reduce als abstrakte Operatoren so zu betrachten, dass ich Listenverständnisse oder Generatoren nicht berücksichtige, fast so, als würde ich eine Implementierungsentscheidung explizit verschieben, indem ich diese Operatoren verwende.
Edit: Dies ist eine ziemlich alte Frage, und meine Meinung zu diesem Thema hat sich etwas geändert.
Zunächst einmal bin ich stark voreingenommen
lambda
, einer Variablen einen Ausdruck zuzuweisen. as python hat nur dafür eine spezielle Syntax (Hinweis,def
). Darüber hinaus haben viele der Anwendungen für Lambda, selbst wenn sie keinen Namen erhalten, vordefinierte (und effizientere) Implementierungen. Zum Beispiel kann das fragliche Beispiel mit just abgekürzt werden(1).__add__
, ohne dass es in einlambda
oder eingeschlossen werden mussdef
. Viele andere gängige Anwendungen können mit einer Kombination der erfüllt seinoperator
,itertools
undfunctools
Module.quelle
(1).__add__
- Das direkte Aufrufen von Dunder-Methoden sollte fast nie passieren. Tausendlambda
Sekunden für jeden direkten Dunder-Anruf.(1).__add__
etwas ungewöhnlich, aber ich würde nicht in die Nähe von "sollte" gehen. Ohne Zweifel finde ich, dass Ersteres weitaus besser lesbar istlambda x: 1 + x
. Wenn wir etwas ähnlicheres wie die Haskells-Slice-Notation hätten,(1+)
wäre das großartig, aber wir müssen mit dem auskommen, was semantisch genau das ist, dem Namen der Dunder-Methode.Betrachtet man ein einfaches Beispiel,
quelle
Wenn Sie das Lambda nur einer Variablen im lokalen Bereich zuweisen möchten, können Sie auch def verwenden, da es besser lesbar ist und in Zukunft einfacher erweitert werden kann:
oder
quelle
from operator import pow;map(pow, someList)
und(a**b for a,b in someList)
sind noch besser lesbar.Eine Verwendung für Lambdas, die ich gefunden habe, sind Debug-Nachrichten.
Da Lambdas träge ausgewertet werden können, können Sie folgenden Code haben:
statt möglicherweise teuer:
Hiermit wird die Formatzeichenfolge verarbeitet, auch wenn der Debug-Aufruf aufgrund der aktuellen Protokollierungsstufe keine Ausgabe erzeugt.
Damit es wie beschrieben funktioniert, muss das verwendete Protokollierungsmodul Lambdas als "Lazy-Parameter" unterstützen (wie mein Protokollierungsmodul).
Die gleiche Idee kann auf jeden anderen Fall einer verzögerten Bewertung zur Wertschöpfung von Inhalten bei Bedarf angewendet werden.
Zum Beispiel dieser benutzerdefinierte ternäre Operator:
anstatt:
Bei Lambdas wird nur der durch die Bedingung ausgewählte Ausdruck ausgewertet, bei Lambdas werden beide ausgewertet.
Natürlich könnten Sie einfach Funktionen anstelle von Lambdas verwenden, aber für kurze Ausdrücke sind Lambdas (c) schlanker.
quelle
logging
bereits eine verzögerte Formatierung:log.debug("this is my message: %r", some_data)
Wird nur formatiert, wenn / wenn die Nachricht angefordert wird.some_data
sich um einen teuren Ausdruck oder einen Funktions- / Methodenaufruf handeln könnte.Ich stimme nosklo zu. Übrigens, auch bei einmaliger Verwendung wegwerfen , meistens möchten Sie nur etwas vom Bedienmodul verwenden.
Z.B :
Sie haben eine Funktion mit dieser Signatur: myFunction (Daten, Rückruffunktion).
Sie möchten eine Funktion übergeben, die 2 Elemente hinzufügt.
Mit Lambda:
Der pythonische Weg:
Oder natürlich ist dies ein einfaches Beispiel, aber das Bedienermodul bietet eine Menge Dinge, einschließlich der Elemente Setter / Getter für Liste und Diktat. Wirklich cool.
quelle
Ein wesentlicher Unterschied besteht darin, dass Sie
def
Funktionen nicht inline verwenden können, was meiner Meinung nach der bequemste Anwendungsfall für einelambda
Funktion ist. Zum Beispiel beim Sortieren einer Liste von Objekten:Ich würde daher vorschlagen, die Verwendung von Lambdas für diese Art von trivialen Operationen beizubehalten, die auch nicht wirklich von der automatischen Dokumentation profitieren, die durch die Benennung der Funktion bereitgestellt wird.
quelle
Lambda ist nützlich, um neue Funktionen zu generieren:
quelle