Was ist vorzuziehen: Lambda-Funktionen oder verschachtelte Funktionen ('def')?


100

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 .

Antworten:


104

Wenn Sie das lambdaeinem Namen zuweisen müssen , verwenden Sie defstattdessen ein. defs sind nur syntaktischer Zucker für eine Aufgabe, daher ist das Ergebnis das gleiche und sie sind viel flexibler und lesbarer.

lambdas kann einmal verwendet werden. Werfen Sie Funktionen weg , die keinen Namen haben.

Dieser Anwendungsfall ist jedoch sehr selten. Sie müssen selten unbenannte Funktionsobjekte weitergeben.

Die eingebauten map()und filter()benötigten Funktionsobjekte, aber Listenverständnisse und Generatorausdrücke sind im Allgemeinen besser lesbar als diese Funktionen und können alle Anwendungsfälle abdecken, ohne dass Lambdas erforderlich sind.

Für die Fälle, in denen Sie wirklich ein kleines Funktionsobjekt benötigen, sollten Sie die operatorModulfunktionen wie operator.addanstelle von verwendenlambda x, y: x + y

Wenn Sie noch einige lambdanicht abgedeckte benötigen , können Sie eine schreiben def, um besser lesbar zu sein. Wenn die Funktion komplexer ist als die im operatorModul, defist a wahrscheinlich besser.

Gute lambdaAnwendungsfälle in der realen Welt sind daher sehr selten.


9
Ich bin mit der Antwort lambdaeinverstanden, wann sie verwendet werden soll , aber ich bin nicht der Meinung, dass dies "sehr selten" ist, es ist üblich für Schlüsselfunktionen sortedoder itertools.groupbyusw., z. B.sorted(['a1', 'b0'], key= lambda x: int(x[1]))
Chris_Rands

30

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

d.addCallback(lambda result: setattr(self, _someVariable, result))

ist ziemlich häufig und prägnanter mit Lambdas.

Der zweite Unterschied besteht darin, was die eigentliche Funktion tun darf.

  • Eine mit 'def' definierte Funktion kann einen beliebigen Python-Code enthalten
  • Eine mit 'lambda' definierte Funktion muss zu einem Ausdruck ausgewertet werden und darf daher keine Anweisungen wie print, import, raise, ... enthalten.

Beispielsweise,

def p(x): print x

funktioniert wie erwartet, während

lambda x: print x

ist ein SyntaxError.

Natürlich gibt es Problemumgehungen - ersetzen Sie printdurch sys.stdout.writeoder importmit __import__. Aber normalerweise ist es in diesem Fall besser, eine Funktion zu verwenden.


22

In diesem Interview sagt Guido van Rossum, er wünschte, er hätte "Lambda" nicht in Python gelassen:

" Q. Mit welcher Funktion von Python sind Sie am wenigsten zufrieden?

Manchmal habe ich Beiträge zu schnell angenommen und später festgestellt, dass es sich um einen Fehler handelt. Ein Beispiel wären einige der funktionalen Programmierfunktionen, wie z. B. Lambda-Funktionen. Lambda ist ein Schlüsselwort, mit dem Sie eine kleine anonyme Funktion erstellen können. Integrierte Funktionen wie Zuordnen, Filtern und Reduzieren führen eine Funktion über einen Sequenztyp wie eine Liste aus.

In der Praxis hat es sich nicht so gut herausgestellt. Python hat nur zwei Bereiche: lokal und global. Dies macht das Schreiben von Lambda-Funktionen schmerzhaft, da Sie häufig auf Variablen in zugreifen möchten Der Bereich, in dem das Lambda definiert wurde, aber aufgrund der beiden Bereiche nicht möglich ist. Es gibt einen Weg, dies zu umgehen, aber es ist eine Art Kludge. Oft scheint es in Python viel einfacher zu sein, nur eine for-Schleife zu verwenden, anstatt damit herumzuspielen Lambda-Funktionen. Map und Freunde funktionieren nur dann gut, wenn bereits eine integrierte Funktion vorhanden ist, die das tut, was Sie wollen.

IMHO, Iambdas können manchmal bequem sein, sind aber normalerweise auf Kosten der Lesbarkeit bequem. Können Sie mir sagen, was dies bewirkt:

str(reduce(lambda x,y:x+y,map(lambda x:x**x,range(1,1001))))[-10:]

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 :)


20
Beachten Sie, dass das Interview ziemlich alt ist und Python längst verschachtelte Bereiche hinzugefügt hat, was das Argument, das er gegen Lambda vorbringt, nicht mehr relevant macht. Ich bin sicher, er bereut Lambda immer noch, aber nicht genug, um es in Python 3.0 zu entfernen.
Thomas Wouters

10
Ihr Beispiel sollte wirklich ein Argument gegen Einzeiler sein, nicht gegen Lambdas. Außerdem sollten Sie die integrierte Summenfunktion verwenden, anstatt mit einem Lambda zu reduzieren: str (Summe (Karte (Lambda x: x ** x, Bereich (1001))) [: - 10]
Triptychon

2
@ThomasWouters: Ich verstehe, dass lambdaes naheliegend war, in 3.0 nicht entfernt zu werden, und dass Guido nicht darum kämpfte, es zu behalten.
Ethan Furman

11

Für n = 1000 gibt es einige Zeitpunkte für den Aufruf einer Funktion gegen ein Lambda:

In [11]: def f(a, b):
             return a * b

In [12]: g = lambda x, y: x * y

In [13]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    f(a, b)
   ....:
100 loops, best of 3: 285 ms per loop

In [14]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    g(a, b)
   ....:
100 loops, best of 3: 298 ms per loop

In [15]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    (lambda x, y: x * y)(a, b)
   ....:
100 loops, best of 3: 462 ms per loop

3
Interessant zu sehen, dass das Lambda und die definierten Versionen in etwa gleichwertig sind. Der letzte Test dauerte länger, da Python wahrscheinlich jedes Mal Speicherplatz zuweisen musste, wenn es diese Lambda-Funktion definierte.
hlin117

Ich denke, dies ist sinnvoll, da die Definition möglicherweise auf lokale Variablen verweist (die sich möglicherweise geändert haben) ... obwohl cpython in dem Fall, in dem dies nicht der Fall ist, wie hier einen besseren Job machen könnte.
Andy Hayden

Verwenden Sie dis.dis; Ihr (Lambda x, y: x * y) erstellt die Funktion in jeder Schleife. Wenn Sie das Lambda vor der Schleife erstellen (auch bekannt als f = Lambda x, y: x * y), entspricht der Bytecode zum Aufrufen der Funktion genau dem von g / f in Ihrem vorherigen Beispiel, daher ist die Lambda-Leistung dieselbe als def Funktion. Also Lambda oder Def als keine Auswirkung, wenn Sie es gleich verwenden. Haben die inverse, erklären die f () Funktion in der Schleife, dann rufen Sie es ...
tito

@tito Ich glaube, genau das zeigen die 3 zeitgesteuerten Beispiele ...
Andy Hayden

@tito oh, du sagst, du definierst die Funktion in der Schleife, klar, aber ich würde argumentieren, dass das ein ungewöhnliches Muster ist. Ich bin mir nicht sicher, warum dies die Abwertung dieses Kommentars erforderte ...
Andy Hayden

7

Performance:

Das Erstellen einer Funktion mit lambdaist etwas schneller als das Erstellen mit def. Der Unterschied ist auf defeinen 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:

# Using non-functional version.

heading(math.sqrt(v.x * v.x + v.y * v.y), math.atan(v.y / v.x))

# Using lambda with functional version.

fheading(v, lambda v: math.sqrt(v.x * v.x + v.y * v.y), lambda v: math.atan(v.y / v.x))

# Using def with functional version.

def size(v):
    return math.sqrt(v.x * v.x + v.y * v.y)

def direction(v):
    return math.atan(v.y / v.x)

deal_with_headings(v, size, direction)

Wie Sie sehen können, ist die lambdaVersion kürzer und "einfacher" in dem Sinne, dass Sie nur lambda 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.
  • lambdaFunktionen, die Variablennamen zugewiesen sind, haben keinen Vorteil gegenüber defFunktionen.
  • 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 lambdaBediener steht in direktem Kontrast zu dieser Tendenz. Darüber hinaus erweitert defdie lambdaFunktion 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 lambdaim Feld durch Mitglieder des operatoroder anderer Module ersetzt werden. Zum Beispiel:

do_something(x, y, lambda x, y: x + y)
do_something(x, y, operator.add)

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 mapund filterFunktionen:

[e for e in some_array if some_condition(e)]
filter(some_array, some_condition)

lambdaund defsind 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.


7

Bevorzugter: Lambda-Funktionen oder verschachtelte Funktionen ( def)?

Die Verwendung eines Lambda gegenüber einer regulären Funktion hat einen Vorteil: Sie werden in einem Ausdruck erstellt.

Es gibt mehrere Nachteile:

  • kein Name (nur '<lambda>')
  • keine docstrings
  • Keine Anmerkungen
  • keine komplexen Aussagen

Sie sind auch beide der gleiche Objekttyp. Aus diesen Gründen ziehe ich es im Allgemeinen vor, Funktionen mit dem defSchlü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

>>> l = lambda: 0
>>> type(l)
<class 'function'>
>>> def foo(): return 0
... 
>>> type(foo)
<class 'function'>
>>> type(foo) is type(l)
True

Da Lambdas Funktionen sind, sind sie erstklassige Objekte.

Sowohl Lambdas als auch Funktionen:

  • kann als Argument weitergegeben werden (wie eine reguläre Funktion)
  • Wenn sie innerhalb einer äußeren Funktion erstellt werden, werden sie zu einem Abschluss über den Einheimischen dieser äußeren 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.

>>> l.__name__
'<lambda>'
>>> foo.__name__
'foo'

Daher können Lambdas nicht programmgesteuert in ihrem Namespace nachgeschlagen werden.

Dies schränkt bestimmte Dinge ein. Zum Beispiel fookann mit serialisiertem Code nachgeschlagen werden, während lnicht:

>>> import pickle
>>> pickle.loads(pickle.dumps(l))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>: 
attribute lookup <lambda> on __main__ failed

Wir können foogut nachschlagen - weil es seinen eigenen Namen kennt:

>>> pickle.loads(pickle.dumps(foo))
<function foo at 0x7fbbbee79268>

Lambdas haben keine Anmerkungen und keine Dokumentzeichenfolge

Grundsätzlich sind Lambdas nicht dokumentiert. Lassen Sie uns umschreiben foo, um besser dokumentiert zu werden:

def foo() -> int:
    """a nullary function, returns 0 every time"""
    return 0

Jetzt hat foo Dokumentation:

>>> foo.__annotations__
{'return': <class 'int'>}
>>> help(foo)
Help on function foo in module __main__:

foo() -> int
    a nullary function, returns 0 every time

Wir haben nicht den gleichen Mechanismus, um Lambdas die gleichen Informationen zu geben:

>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda (...)

Aber wir können sie hacken:

>>> l.__doc__ = 'nullary -> 0'
>>> l.__annotations__ = {'return': int}
>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda ) -> in
    nullary -> 0

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.

>>> lambda: if True: 0
  File "<stdin>", line 1
    lambda: if True: 0
             ^
SyntaxError: invalid syntax

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:

import timeit

def return_nullary_lambda(return_value=0):
    return lambda: return_value

def return_nullary_function(return_value=0):
    def nullary_fn():
        return return_value
    return nullary_fn

Und nun:

>>> min(timeit.repeat(lambda: return_nullary_lambda(1)))
0.24312214995734394
>>> min(timeit.repeat(lambda: return_nullary_function(1)))
0.24894469301216304

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 defstatt mit zu erstellen lambda.


6

Ich stimme dem Rat von nosklo zu: Wenn Sie der Funktion einen Namen geben müssen, verwenden Sie def. Ich reserviere lambdaFunktionen für Fälle, in denen ich nur einen kurzen Codeausschnitt an eine andere Funktion übergebe, z.

a = [ (1,2), (3,4), (5,6) ]
b = map( lambda x: x[0]+x[1], a )

3
In den meisten Kombinationen von Karte / Lambda können Sie es durch ein Listenverständnis oder eine geeignetere Funktion ersetzen. Zum Beispiel "map (sum, a)" oder "[x [0] + x [1] für x in a]"
John Millikin

Ja das stimmt. Manchmal bevorzuge ich jedoch map (). Dies war meist nur ein erfundenes Beispiel für die Verwendung einer Inline-Funktion.
Dan Lenski

genau ... Die meisten Beispiele sind erfunden, weil die Verwendung unnatürlich ist und es in den meisten Fällen praktisch bessere Möglichkeiten gibt.
Nosklo

5

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-Dimension defaultdict.
Hier ist ein Beispiel:

from collections import defaultdict
d = defaultdict(lambda: defaultdict(list))
d['Foo']['Bar'].append(something)

Ich finde es lesbarer als ein deffür die zweite Dimension zu erstellen . Dies ist für höhere Dimensionen noch wichtiger.


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.
DylanYoung

3

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:

x = [f for f in range(1, 40) if f % 2]

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.


3

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 defed-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 ein lambdaoder eingeschlossen werden muss def. Viele andere gängige Anwendungen können mit einer Kombination der erfüllt sein operator, itertoolsund functoolsModule.


1
(1).__add__- Das direkte Aufrufen von Dunder-Methoden sollte fast nie passieren. Tausend lambdaSekunden für jeden direkten Dunder-Anruf.
Ethan Furman

1
@EthanFurman: Nun, meiner Erfahrung nach sind Anrufe der Natur (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 ist lambda 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.
SingleNegationElimination

2
  • Rechenzeit.
  • Funktion ohne Namen.
  • Um eine Funktion zu erreichen, verwenden viele Funktionen.

Betrachtet man ein einfaches Beispiel,

# CREATE ONE FUNCTION AND USE IT TO PERFORM MANY OPERATIONS ON SAME TYPE OF DATA STRUCTURE.
def variousUse(a,b=lambda x:x[0]):
    return [b(i) for i in a]

dummyList = [(0,1,2,3),(4,5,6,7),(78,45,23,43)]
variousUse(dummyList)                           # extract first element
variousUse(dummyList,lambda x:[x[0],x[2],x[3]]) # extract specific indexed element
variousUse(dummyList,lambda x:x[0]+x[2])        # add specific elements
variousUse(dummyList,lambda x:x[0]*x[2])        # multiply specific elements

1

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:

fun = lambda a, b: a ** b # a pointless use of lambda
map(fun, someList)

oder

def fun(a, b): return a ** b # more readable
map(fun, someList)

Beides from operator import pow;map(pow, someList)und (a**b for a,b in someList)sind noch besser lesbar.
InQβ

1

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:

log.debug(lambda: "this is my message: %r" % (some_data,))

statt möglicherweise teuer:

log.debug("this is my message: %r" % (some_data,))

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:

def mif(condition, when_true, when_false):
    if condition:
         return when_true()
    else:
         return when_false()

mif(a < b, lambda: a + a, lambda: b + b)

anstatt:

def mif(condition, when_true, when_false):
    if condition:
         return when_true
    else:
         return when_false

mif(a < b, a + a, b + b)

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.


1
NB hat loggingbereits eine verzögerte Formatierung: log.debug("this is my message: %r", some_data)Wird nur formatiert, wenn / wenn die Nachricht angefordert wird.
j08lue

Die @ j08lue Lambda-Methode überspringt die Auswertung von allem, falls die Debug-Ausgabe nicht erzeugt wird, falls Sie zeigen, dass es some_datasich um einen teuren Ausdruck oder einen Funktions- / Methodenaufruf handeln könnte.
Glushiator

0

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:

myFunction(data, (lambda x, y : x + y))

Der pythonische Weg:

import operator
myFunction(data, operator.add)

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.


-1

Ein wesentlicher Unterschied besteht darin, dass Sie defFunktionen nicht inline verwenden können, was meiner Meinung nach der bequemste Anwendungsfall für eine lambdaFunktion ist. Zum Beispiel beim Sortieren einer Liste von Objekten:

my_list.sort(key=lambda o: o.x)

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.


-2

Lambda ist nützlich, um neue Funktionen zu generieren:

>>> def somefunc(x): return lambda y: x+y
>>> f = somefunc(10)
>>> f(2)
12
>>> f(4)
14
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.