Création de fonctions dans une boucle
J'essaie de créer des fonctions à l'intérieur d'une boucle et de les stocker dans un dictionnaire. Le problème est que toutes les entrées du dictionnaire semblent finir par correspondre à la dernière fonction créée. Le code va comme ceci:
d = {}
def test(**kwargs):
for k in kwargs:
def f():
print(k, kwargs[k])
d[k] = f
f()
test(foo=1, bar=2)
print('should print the same output as before')
d['foo']()
d['bar']()
Cette sortie:
foo 1
bar 2
should print the same output as before
bar 2
bar 2
Une idée de pourquoi?
1 réponses
Vous rencontrez un problème avec late binding - chaque fonction recherche k
le plus tard possible (ainsi, lorsqu'elle est appelée en dehors de test
, cela se produit après la fin de la boucle).
Facilement fixé en forçant la liaison précoce: changez def f():
en def f(k=k):
comme ceci:
def f(k=k):
print(k, kwargs[k])
Les valeurs par Défaut (la droite k
dans k=k
est une valeur par défaut pour le nom d'argument k
, ce qui est la gauche k
dans k=k
) sont regardé def
, non pas pendant l' call
temps, donc, essentiellement, ils sont un moyen de rechercher spécifiquement la liaison précoce.
Si vous êtes inquiet à propos de f
obtenir un argument supplémentaire (et donc potentiellement être appelé à tort), il y a une manière plus sophistiquée qui implique l'utilisation d'une fermeture comme une "usine de fonctions":
def make_f(kwargs, k):
def f():
print(k, kwargs[k])
return f
Et dans votre boucle utilisez f = make_f(kwargs, k)
au lieu de l'instruction def
.