En revoyant le didacticiel Python de W3Schools, je suis perplexe devant leur exemple de lambda.
D'où diable la valeur de la variable "a" vient-elle? Bien sûr, "a" est le lambda - mais d'où vient-il une valeur?
def myfunc(n): return lambda a : a * n mytripler = myfunc(3) print(mytripler(11))
Si j'appelle print (myfunc (3)) seul, j'obtiens un Erreur. La fonction ne fonctionne que si la fonction est appelée par une autre fonction. Comment lambda a-t-il connaissance de tout cela?
Je crains de manquer quelque chose de très fondamental à propos des fonctions lambda.
3 Réponses :
Les lambdas ne sont que des raccourcis pour les déclarations complètes. Cela rend votre exemple fonctionnellement identique à celui-ci:
def myfunc(n): def inner(a): return a * n return inner
Le lambda est une fonction, et lorsque vous l'appelez, vous lui fournissez un argument (a dans cet exemple).
p>
Ce que fait myfunc (3)
, c'est qu'il affecte 3 à n
, puis cette valeur est utilisée dans l'expression lambda. L'expression devient donc 3 * a
. Votre fonction lambda a une variable indépendante a
. Lorsque vous retournez lambda a: a * n
votre mytripler
agit maintenant comme un objet (fonction) dont l'argument est a
et l'action est de calculer a * 3
. Donc, finalement, lorsque vous appelez
mytripler(11)
vous attribuez 11 à votre variable indépendante a
, obtenant ainsi 33
a
dans votre exemple se voit attribuer la valeur 11.
Pensez à la définition d'une fonction lambda comme "lorsque vous lui donnez une entrée, renvoyez ceci". Vous pouvez nommer l'entrée n'importe quoi, appelons-la donc x. lambda x: x + 1
signifie "étant donné une entrée que nous appellerons x
: return x + 1
".
Vous avez une couche supplémentaire d'une fonction renvoyant un lambda, mais si nous la décomposons, le but de myfunc
est de générer dynamiquement une fonction lambda. Lorsque vous appelez myfunc (3)
, vous avez maintenant entre les mains une fonction lambda qui ressemble à ceci: lambda a: a * 3
. C'est ce que contient la variable mytripler
. Si vous print (mytripler)
, vous voyez quelque chose comme ceci:
, qui vous indique que c'est une fonction lambda. mytripler
contient une fonction, pas une valeur.
Que fait cette fonction lambda? Il dit "étant donné un paramètre d'entrée que nous appellerons a
: return a * 3
".
Que faites-vous des fonctions? Vous les appelez! Et envoyez tous les paramètres avec l'appel. Combien de paramètres prend notre fonction lambda? Cependant, de nombreuses variables précèdent les deux points dans la définition de la fonction lambda, dans ce cas une: a
. Nous appelons donc le lambda stocké dans mytripler
en lui envoyant un paramètre: mytripler (11)
. 11 est l'entrée de la fonction lambda, qui est d'abord affectée à a
et renvoie a * 3 -> 33
.
Vous pourriez avoir un lambda qui prend 2 entrées que nous appellerons x
et y
:
additionneur = lambda x, y: x + y
Que fait ce lambda? Il dit "étant donné 2 entrées que nous appellerons x
et y
: renvoyer leur somme". Comment appelez-vous cela? Vous devez appeler additionneur
avec deux paramètres: additionneur (2,3)
renvoie 5
. 2
est attribué à x
, 3
est affecté à y
et la fonction renvoie leur somme.
Et si nous appelons additionneur (1)
?
TypeError:
À partir de là, vous pouvez voir que Python sait combien de paramètres d'entrée la fonction lambda attend de sa définition et ne peut pas fonctionner sans obtenir au préalable tous les paramètres dont elle a besoin.
Je comprends ... je déteste ça. C'est la meilleure façon de générer du code spaghetti que j'ai jamais vu. Merci pour l'explication.
Haha, je pense que vous pourriez le détester parce que vous l'avez rencontré comme un exemple de tutoriel abstrait, donc son avantage n'est pas évident. Je soupçonne que si la bonne opportunité est donnée, lorsqu'un lambda se présente comme une sténographie agréable et compacte qui vous évite de définir une fonction à une ligne juste pour pouvoir l'appeler une fois, vous pourriez commencer à les aimer.
Oui, je vois comment cela aurait pu être utile pour définir des fonctionnalités à la volée. Dans le didacticiel Cet exemple n'est clairement pas clair (nulle part l'explication de l'origine de «a») n'est, comme vous le faites remarquer, utile.
C'est un paramètre . comme si vous aviez fait
def f (a): return a * n
. Etprint (myfunc (3))
ne produit pas d'erreur , imprime la valeur de retour demyfunc
, qui est une fonctionJ'obtiens ". at 0x7fcda75e8d08>" à la suite de "
print (myfunc (3))
. Cette n'est pas une erreur mais une représentation textuelle (peu conviviale pour les débutants) d'une fonction. Comparezprint (print)
, ce qui me donne "