Liaison de Python lambda aux valeurs locales
Le code suivant crache 1
deux fois, mais je m'attends à voir 0
et ensuite 1
.
def pv(v):
print v
x = []
for v in range(2):
x.append(lambda: pv(v))
for xx in x:
xx()
Je m'attendais à ce que python lambdas se lie à la référence vers laquelle pointe une variable locale, dans les coulisses. Cependant cela ne semble pas être le cas. J'ai rencontré ce problème dans un grand système où le lambda fait l'équivalent C++ moderne d'une liaison ('boost::bind' par exemple) où, dans ce cas, vous vous lieriez à un ptr intelligent ou copieriez construire une copie pour le lambda.
Alors, comment lier une variable locale à une fonction lambda et lui faire conserver la référence correcte lorsqu'elle est utilisée? Je suis assez abasourdi par le comportement car je ne m'attendrais pas à cela d'un langage avec un ramasse-miettes.
Solution du problème
Passez x.append(lambda: pv(v))
à x.append(lambda v=v: pv(v))
.
Vous vous attendez à ce que "python lambdas se lie à la référence vers laquelle une variable locale pointe, derrière la scène", mais ce n'est pas ainsi que Python fonctionne. Python recherche le nom de la variable au moment où la fonction est appelée, et non lors de sa création. L'utilisation d'un argument par défaut fonctionne car les arguments par défaut sont évalués lorsque la fonction est créée, et non lorsqu'elle est appelée.
Ce n'est pas quelque chose de spécial à propos des lambdas. Considérer:
x = "before foo defined"
def foo():
print x
x = "after foo was defined"
foo()
impressions
after foo was defined
Commentaires
Enregistrer un commentaire