Excuses si cela a été demandé auparavant, mais je ne pouvais le voir nulle part.
En gros, j'ai rencontré un scénario dans lequel je dois utiliser une instruction if dans une fonction lambda. Ce qui rend la tâche difficile, c’est que, idéalement, il doit figurer dans une seule ligne de code (si cela est même possible?)
Normalement, j'écrirais ceci:
T = 250
if (T > 200):
rate = 200*exp(-T)
else:
rate = 400*exp(-T)
return (rate)
Cependant, j'en ai besoin pour ressembler à ceci:
rate = lambda(T) : if (T>200): return(200*exp(-T)); else: return(400*exp(-T))
Je me rends compte que la chose la plus facile à faire serait de prendre la décision en dehors des fonctions lambda, puis d’avoir une fonction lambda séparée pour chaque cas, mais ce n’est pas vraiment approprié ici. Les fonctions lambda sont stockées dans un tableau et accédées en cas de besoin, chaque élément du tableau correspondant à un "débit" particulier, de sorte que deux rangées distinctes correspondant au même "débit" gâcheraient tout. Toute aide serait grandement appréciée, ou si ce n’était pas possible, une confirmation de la part d’autres serait bien :)
Utilisez le exp1 if cond else exp2
syntaxe.
rate = lambda T: 200*exp(-T) if T>200 else 400*exp(-T)
Notez que vous n'utilisez pas return
dans les expressions lambda.
La bonne façon de faire est simple:
def rate(T):
if (T > 200):
return 200*exp(-T)
else:
return 400*exp(-T)
Il n'y a absolument aucun avantage à utiliser lambda
ici. La seule chose pour laquelle lambda
est utile est de vous permettre de créer des fonctions anonymes et de les utiliser dans une expression (par opposition à une instruction). Si vous assignez immédiatement le lambda
à une variable, celle-ci n'est plus anonyme et est utilisée dans une instruction. Vous ne faites donc que rendre votre code moins lisible sans raison.
La fonction rate
définie de cette façon peut être stockée dans un tableau, transmise, appelée, etc. de la même manière qu'une fonction lambda. Ce sera exactement la même chose (sauf un peu plus facile à déboguer, introspecter, etc.).
D'un commentaire:
Eh bien, la fonction devait s’intégrer dans une seule ligne, ce que je ne pensais pas pouvoir faire avec une fonction nommée?
Je ne peux imaginer aucune raison valable pour que la fonction doive être intégrée dans une seule ligne. Mais bien sûr, vous pouvez le faire avec une fonction nommée. Essayez ceci dans votre interprète:
>>> def foo(x): return x + 1
De plus, ces fonctions sont stockées sous forme de chaînes qui sont ensuite évaluées à l'aide de "eval", ce que je ne savais pas exactement comment faire avec les fonctions habituelles.
Encore une fois, même s’il est difficile d’être sûr à 100% sans savoir pourquoi, mais je suis au moins à 99% sûr que vous n’avez aucune raison ou une mauvaise raison pour cela. Presque chaque fois que vous pensez que vous voulez passer Python fonctionne comme des chaînes et appelez eval
pour que vous puissiez les utiliser, vous voulez simplement passer Python fonctionne comme des fonctions et les utilise comme des fonctions.
Mais si ce n’est vraiment ce dont vous avez besoin ici, utilisez exec
au lieu de eval
.
Vous n'avez pas indiqué quelle version de Python vous utilisez. Dans 3.x, la fonction exec
a exactement la même signature que la eval
fonction:
exec(my_function_string, my_globals, my_locals)
En 2.7, exec
est une instruction, pas une fonction - mais vous pouvez toujours l'écrire dans la même syntaxe que dans 3.x (tant que vous n'essayez pas d'attribuer la valeur de retour à rien) et cela fonctionne.
Dans les versions 2.x antérieures (avant la version 2.6, je pense?), Vous devez le faire comme ceci:
exec my_function_string in my_globals, my_locals
Oui, vous pouvez utiliser la syntaxe abrégée pour les instructions if
.
rate = lambda(t): (200 * exp(-t)) if t > 200 else (400 * exp(-t))
Notez que vous n'utilisez pas d'instructions return
explicites dans lambda
s.
J'ai trouvé que je pourrais utiliser des déclarations "if-then" dans un lambda. Par exemple:
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,
}
Au moment où vous dites rate = lambda whatever...
vous avez vaincu le point de lambda et vous devez définir une fonction. Mais si vous voulez un lambda, vous pouvez utiliser 'et' et 'ou'
lambda(T): (T>200) and (200*exp(-T)) or (400*exp(-T))