Lorsque tu parcours ta list et crées tes lambdas, tu crées n fonctions (6 dans ton cas) qui sont toutes liées au même namespace (dans lequel elles ont été créées).
Quand Tkinter appelle ces callbacks, elles vont toutes aller chercher la valeur de key dans le namespace les contenant. Comme elles partagent le même namespace, elle trouve la même valeur. Et la valeur de key, c'est "but6", la dernière valeur attribuer à key.
La solution est de forcer la "résolution" de key au moment où la lambda est créée et pas quand elle est exécutée.
Pour ce faire, l'idiome courant en python est d'utiliser un argument ayant une valeur par défaut:
# code simplifié pour l'exemple :list=["but1","but2","but3","but4","but5","but6"]forkeyinlist:ui.key=Button(ui,text=key,command=lambdak=key:print(k))ui.key.pack(side=LEFT,padx=2,pady=2)
Ainsi, lorsque la lambda est exécutée, elle utilise la valeur de k (son argument) qui à pour valeur la valeur de key (variable global) au moment de sa définition.
Il existe aussi une autre façon de faire, créer un namespace par fonction, dans lequel la closure ira chercher:
defcreate_callback(key):"""Cet fonction va créer une callback et la retourner à l'appelant Comme chaque appel de fonction crée un nouveau namespace et que la callback est créée dans ce namespace, chaque callback a son namespace. """def_callback():print(key)return_callbacklist=["but1","but2","but3","but4","but5","but6"]forkeyinlist:ui.key=Button(ui,text=key,command=create_callback(key))ui.key.pack(side=LEFT,padx=2,pady=2)
# Namespace et closure.
Posté par GaMa (site web personnel) . En réponse au message Problème de callback avec Tkinter. Évalué à 6.
C'est un problème de python et pas de tkinter.
Lorsque tu parcours ta list et crées tes lambdas, tu crées n fonctions (6 dans ton cas) qui sont toutes liées au même namespace (dans lequel elles ont été créées).
Quand Tkinter appelle ces callbacks, elles vont toutes aller chercher la valeur de key dans le namespace les contenant. Comme elles partagent le même namespace, elle trouve la même valeur. Et la valeur de key, c'est "but6", la dernière valeur attribuer à key.
La solution est de forcer la "résolution" de key au moment où la lambda est créée et pas quand elle est exécutée.
Pour ce faire, l'idiome courant en python est d'utiliser un argument ayant une valeur par défaut:
Ainsi, lorsque la lambda est exécutée, elle utilise la valeur de k (son argument) qui à pour valeur la valeur de key (variable global) au moment de sa définition.
Il existe aussi une autre façon de faire, créer un namespace par fonction, dans lequel la closure ira chercher:
Matthieu Gautier|irc:starmad