wake-up-neo.com

Bedingte Anweisung in einer einzeiligen Lambda-Funktion in Python?

Entschuldigung, wenn dies schon einmal gefragt wurde, aber ich konnte es nirgendwo sehen.

Im Wesentlichen bin ich auf ein Szenario gestoßen, in dem ich eine if-Anweisung in einer Lambda-Funktion verwenden muss. Was es schwierig macht, ist, dass es idealerweise in einer einzigen Codezeile stehen muss (wenn das überhaupt möglich ist?)

Normalerweise würde ich folgendes schreiben:

T = 250

if (T > 200):
    rate = 200*exp(-T)
else:
    rate = 400*exp(-T)

return (rate)

Allerdings muss es so aussehen:

rate = lambda(T) : if (T>200): return(200*exp(-T)); else: return(400*exp(-T))

Mir ist klar, dass es einfacher ist, Entscheidungen außerhalb der Lambda-Funktionen zu treffen und dann für jeden Fall eine eigene Lambda-Funktion zu haben, die hier jedoch nicht wirklich geeignet ist. Die Lambda-Funktionen werden in einem Array gespeichert und bei Bedarf aufgerufen, wobei jedes Array-Element einer bestimmten "Rate" entspricht, sodass zwei separate Zeilen für dieselbe "Rate" die Sache durcheinander bringen würden. Jede Hilfe wäre sehr dankbar, oder wenn es nicht möglich ist, wären einige Bestätigungen von anderen nett :)

56
Nathan Bush

Verwenden Sie die exp1 if cond else exp2 Syntax.

rate = lambda T: 200*exp(-T) if T>200 else 400*exp(-T)

Beachten Sie, dass Sie return nicht in Lambda-Ausdrücken verwenden.

83
shx2

Der richtige Weg dazu ist einfach:

def rate(T):
    if (T > 200):
        return 200*exp(-T)
    else:
        return 400*exp(-T)

Es ist absolut nicht vorteilhaft, hier lambda zu verwenden. Das einzige, wofür lambda gut ist, ist das Erstellen anonymer Funktionen und deren Verwendung in einem Ausdruck (im Gegensatz zu einer Anweisung). Wenn Sie einer Variablen sofort lambda zuweisen, ist sie nicht mehr anonym und wird in einer Anweisung verwendet, sodass Ihr Code ohne Grund weniger lesbar ist.

Die auf diese Weise definierte Funktion rate kann in einem Array gespeichert, weitergegeben, aufgerufen usw. werden, genauso wie es eine Lambda-Funktion tun könnte. Es wird genau das gleiche sein (außer ein bisschen einfacher zu debuggen, nach innen zu schauen, etc.).


Aus einem Kommentar:

Nun, die Funktion musste in eine Zeile passen, was ich nicht für möglich gehalten habe, mit einer benannten Funktion?

Ich kann mir keinen guten Grund vorstellen, warum die Funktion jemals in eine Zeile passen müsste. Sie können dies jedoch mit einer benannten Funktion tun. Versuchen Sie dies in Ihrem Dolmetscher:

>>> def foo(x): return x + 1

Auch diese Funktionen werden als Strings gespeichert, die dann mit "eval" ausgewertet werden, was ich mit normalen Funktionen nicht sicher war.

Auch wenn es schwierig ist, 100% ig sicher zu sein, ohne eine Ahnung zu haben, warum Sie das tun, bin ich mir zu 99% sicher, dass Sie keinen Grund oder einen schlechten Grund dafür haben. Fast jedes Mal, wenn Sie denken, Sie möchten Python als Zeichenfolgen übergeben und eval aufrufen, damit Sie sie verwenden können, möchten Sie Python fungiert als Funktionen und verwendet sie als Funktionen.

Aber mit der Möglichkeit, dass dies wirklich das ist, was Sie hier brauchen: Verwenden Sie einfach exec anstelle von eval.

Sie haben nicht erwähnt, welche Version von Python Sie verwenden. In 3.x hat die Funktion exec genau dieselbe Signatur wie die eval Funktion:

exec(my_function_string, my_globals, my_locals)

In 2.7 ist exec eine Anweisung, keine Funktion - Sie können sie jedoch in derselben Syntax wie in 3.x schreiben (solange Sie nicht versuchen, sie zuzuweisen) der Rückgabewert auf alles) und es funktioniert.

In früheren 2.x (vor 2.6, denke ich?) Müssen Sie es stattdessen so machen:

exec my_function_string in my_globals, my_locals
20
abarnert

Ja, Sie können die Kurzschrift-Syntax für if -Anweisungen verwenden.

rate = lambda(t): (200 * exp(-t)) if t > 200 else (400 * exp(-t))

Beachten Sie, dass Sie auch in returns keine expliziten lambda -Anweisungen verwenden.

7
Silas Ray

Ich fand, dass ich "Wenn-Dann" -Anweisungen in einem Lambda verwenden KÖNNTE. Zum Beispiel:

eval_op = {
    '|'  : lambda x,y: eval(y) if (eval(x)==0) else eval(x),
    '&'  : lambda x,y: 0 if (eval(x)==0) else eval(y),
    '<'  : lambda x,y: 1 if (eval(x)<eval(y)) else 0,
    '>'  : lambda x,y: 1 if (eval(x)>eval(y)) else 0,
}
5
pkmccroskey

Bis Sie sagen, rate = lambda whatever... Sie haben den Lambda-Punkt besiegt und sollten nur eine Funktion definieren. Aber wenn Sie ein Lambda wollen, können Sie 'und' und 'oder'

lambda(T): (T>200) and (200*exp(-T)) or (400*exp(-T))
4
tdelaney