Vous êtes ici : Accueil / Forums & ML / Forums Python / Forum général Python / Attribution d'un argument par une boucle

Attribution d'un argument par une boucle

Remonter à Forum général Python
  • Attribution d'un argument par une boucle

    Envoyé par JemS le 27 Février 2012 à 22:00
    Bonsoir à tous,

    Petit problème python/Tkinter
    J'ai une liste "figs" de tupples (nom,argument)

    En utilisant le code suivant, les boutons sont créés mais lorsque je clique, tous utilisent l'argument du dernier tupple de la liste...
    Quelqu'un aurait-il une solution simple?

    for fig in figs:
    Button(parent,text=fig[0],command=lambda:grille.modify(fig[1])).grid(row=figs.index(fig),column=0)

    Merci d'avance

    JemS
    • Re: Attribution d'un argument par une boucle

      Envoyé par jacko le 28 Février 2012 à 13:50
      Bonjour,

      Oui, c'est un classique !

      Explication : le corps d'une fonction (la lambda ici) n'est évalué qu'au moment de l'exécution, non de la définition. L'expression "fig[ 1 ]" est donc ici (dans votre implémentation) conservée litéralement dans la command associée au bouton ; lorsqu'elle est évaluée (au moment du clic), fig vaut bien la dernière valeur qu'il avait en fin de boucle.

      Il faut écrire :


      for fig in figs:
      Button(parent,
      text=fig[0],
      command=lambda toto=fig:
      grille.modify(toto[1])). \
      grid(row=figs.index(fig),column=0)


      Les valeurs par défaut des arguments d'une fonction, au contraire, sont évalués lors de la définition. Donc dans "toto=fig", fig est évalué immédiatement, à chaque itération, et la valeur est stockée comme valeur par défaut de l'argument toto. Lorsque la fonction est appelée au clic, comme l'argument toto n'est pas fourni, il prend sa valeur par défaut qui a été stockée.

      Note : à la place de toto=fig, on aurait pu mettre fig=fig, et dans le corps de la fonction appeler fig[ 1 ], mais ça embrouille pour rien !

      Autre chose : plutôt que row=figs.index(fig), il serait plus simple d'utiliser enumerate comme suit :


      for i,fig in enumerate(figs):
      Button(....).grid(row=i,column=0)

Rendu par Ploneboard