IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

définir objet dans une class à partir d'une variable


Sujet :

Python

  1. #1
    Membre averti Avatar de temabul
    Homme Profil pro
    Informatique de Loisir
    Inscrit en
    Février 2015
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Informatique de Loisir

    Informations forums :
    Inscription : Février 2015
    Messages : 26
    Par défaut définir objet dans une class à partir d'une variable
    Bonjour,
    Je n'arrive pas à voir comment faire.
    L'intérêt ici est de ne pas devoir taper 26 fois des lignes similaires, mais c'est fréquemment que j'ai à faire à des problèmes similaires.
    Je sais que la ligne 12 ne va pas mais quoi faire.
    Merci de m'aider.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    import tkinter as tk
     
     
    class Appli1(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
            self.creer_widgets()
     
        def creer_widgets(self):
            self.grid()
            for lettre in ["A","B","C"]:
                self.bout_lettre = "bout"+lettre
                self.bout_lettre = tk.Button(self, text=lettre, width="10", height="10",
                                        command=lambda i=lettre: [self.imprime_lettre(lettre)])
     
            self.bout_A.grid(row=1, column=1)
            self.bout_B.grid(row=1, column=2)
            self.bout_C.grid(row=1, column=3)
     
        def imprime_lettre(self, lettre):
            print(lettre)
     
     
    if __name__ == "__main__":
        app = Appli1()
        app.mainloop()

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 762
    Par défaut
    Salut,

    N objets similaires, c'est une collection et les collections en Python se réalisent avec des listes, des dictionnaires,... et une seule variable suffit pour accéder à la collection suivie d'un index ou d'une clef pour récupérer les différents objets.

    A vous de revoir les chapitres qui montrent comment s'en servir dans votre tuto. préféré et de les assimiler pour y penser "collection" lorsque vous vous retrouvez dans des cas semblables.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par temabul Voir le message
    Je sais que la ligne 12 ne va pas
    Ce n'est pas tant la ligne 12 qui ne va pas, c'est l'ensemble "ligne 12 + ligne 13".
    En effet, écrire var=truc puis juste en dessous var=autre_truc, quel que soit le langage, ça reste une inutilité absolue.

    Citation Envoyé par temabul Voir le message
    mais quoi faire.
    Solution de merde: passer par eval()
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >>> bout_a="toto"
    >>> bout_b="titi"
    >>> x="a"
    >>> print(eval("bout_%s" % x))
    toto
    >>> x="b"
    >>> print(eval("bout_%s" % x))
    titi

    Solution pérenne, sensée et réfléchie: poser clairement son besoin et utiliser un outil approprié. Comme le dit wiztricks, devoir gérer n items ce n'est pas une nouveauté, ça a toujours existé en prog et c'est pour cela que tous les langages de prog un minimum évolués connaissent le concept de tableau. Ok il faut commencer par poser les bases et ça peut paraitre astreignant mais ensuite le temps passé est récupéré au centuple.

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import tkinter as tk
     
    class Appli1(tk.Tk):
    	__lettres="ABCD"
    	def __init__(self):
    		super().__init__()
    		self.__creer_widgets()
    	# __init__()
     
    	def __creer_widgets(self):
    		self.grid()
    		self.bout=dict(
    			(
    				lettre,
    				tk.Button(
    					self,
    					text=lettre,
    					width="10",
    					height="10",
    					command=lambda i=lettre: self.imprime_lettre(i),	# Attention, c'est "i" qu'il faut utiliser et non pas "lettre" !!! - Et pas besoin de list pour ça
    				),
    			) for lettre in Appli1.__lettres
    		)
    		for (i, lettre) in enumerate(Appli1.__lettres, 1):
    			self.bout[lettre].grid(row=1, column=i)
    	# __creer_widgets()
     
    	def imprime_lettre(self, lettre): print(lettre)
    # class Appli1
     
    if __name__ == "__main__":
    	app = Appli1()
    	app.mainloop()
    # if
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre averti Avatar de temabul
    Homme Profil pro
    Informatique de Loisir
    Inscrit en
    Février 2015
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Informatique de Loisir

    Informations forums :
    Inscription : Février 2015
    Messages : 26
    Par défaut
    Merci beaucoup pour ces réponses rapides.

    Je ne prenais pas le problème par le bon bout.

    Mais en fait, les widgets tkinter n'ont plus de nom, donc je ne peux pas par la suite modifier l'un d'entre eux (par exemple le placer en "hidden".
    En fait, même si j'ai mal posé ma question, c'est bien là qu'est mon problème : les créer et leur donner un nom à ces widgets (à partir d'un paramètre).

  5. #5
    Membre averti Avatar de temabul
    Homme Profil pro
    Informatique de Loisir
    Inscrit en
    Février 2015
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Informatique de Loisir

    Informations forums :
    Inscription : Février 2015
    Messages : 26
    Par défaut
    Je sais très bien que de marquer self.bouton[i] ne correspond à rien tant que self.bouton n'est pas défini.
    Mais que faire et est-ce un problème spécifique à Tkinter ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import tkinter as tk
     
    class Appli1(tk.Tk):
     
        def __init__(self):
            tk.Tk.__init__(self)
            self.lettres = "ABCD"
            self.__creer_widgets()
     
        def __creer_widgets(self):
            self.grid()
     
    # --------------------- fonctionne ------------------------------------------------
     
            bouton = [0] * 26
            for i in range(26):
                bouton[i] = tk.Button(self, text=i, command=lambda x=i: print(x))
            bouton[8].grid(row=1, column=2)
            bouton[8].configure(bg='yellow')
     
     
     # --------------ne fonctionne pas -------_tkinter.tkapp' object has no attribute 'bouton' (ligne 27)
     
            for (i, lettre) in enumerate(self.lettres, 1):
                self.bouton[i] = tk.Button(self, text=lettre, command=lambda x=i: print(x))
     
            self.bouton[2].grid(row=2, column=4)
     
     
    if __name__ == "__main__":
        app = Appli1()
        app.mainloop()

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 762
    Par défaut
    Citation Envoyé par temabul Voir le message
    Je sais très bien que de marquer self.bouton[i] ne correspond à rien tant que self.bouton n'est pas défini.
    Mais que faire et est-ce un problème spécifique à Tkinter ?
    Une liste est une collection qui n'a rien à voir avec tkinter.
    Et si vous ne savez pas qu'on peut y ajouter des éléments dynamiquement, c'est que vous êtes passé un peu trop vite sur les chapitres qui montrent comment çà marche de votre tuto. préféré (ou que c'est un mauvais tuto.).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Membre averti Avatar de temabul
    Homme Profil pro
    Informatique de Loisir
    Inscrit en
    Février 2015
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Informatique de Loisir

    Informations forums :
    Inscription : Février 2015
    Messages : 26
    Par défaut
    Alors encore merci,
    Ça y est, j'ai compris.(enfin je crois)
    En réutilisant le même dictionnaire plusieurs fois. Donc, voici ma solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    import tkinter as tk
     
     
    class Appli1(tk.Tk):
        __lettres = "ABCD"
     
        def __init__(self):
            super().__init__()
            self.__creer_widgets()
     
        def __creer_widgets(self):
            self.grid()
            self.bout = dict(
                (
                    lettre,
                    tk.Button(
                        self,
                        text=lettre,
                        width="10",
                        height="10",
                        command=lambda i=lettre: self.imprime_lettre(i),
                    ),
                ) for lettre in Appli1.__lettres
            )
            for (i, lettre) in enumerate(self.__lettres, 1):
                self.bout[lettre].grid(row=1, column=i)
     
        def imprime_lettre(self, lettre): print(lettre)
     
        def change_couleur(self,bouton):
            for (i, lettre) in enumerate(self.__lettres, 1):
                if lettre == bouton:
                    self.bout[lettre].configure(bg="yellow")
     
     
    if __name__ == "__main__":
        app = Appli1()
        app.change_couleur('B')
        app.mainloop()
    Mais cela ne fonctionne pas si à la place de __lettres je défini self.lettre = "ABCD" dans le __init__ et bien sûr modifie les différents appels à cet objet.

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 762
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 762
    Par défaut
    Citation Envoyé par temabul Voir le message
    Mais en fait, les widgets tkinter n'ont plus de nom, donc je ne peux pas par la suite modifier l'un d'entre eux (par exemple le placer en "hidden".
    Pour modifier l'état d'un objet, il suffit d'accéder à cet objet pour lui appliquer une méthode. Par exemple puisque vous aimez jouer avec les classes vous pourriez créer une variété de Button qui passe dans l'état hidden lorsqu'on clique dessus.

    Vous pourriez aussi ajouter le Button en paramètre à la méthode imprime_lettre pour qu'en plus d'afficher la lettre, elle masque le Button.

    Côté tkinter vous pourriez récupérer la case de la grille qui à été cliquée et le widget qu'il y a dedans...

    Vous voyez il y a plein de méthode pour récupérer l'objet sur lequel on a cliqué et lui appliquer une méthode... et du travail pour arriver à les faire fonctionner histoire de voir laquelle utiliser suivant le cas histoire de ne pas vous retrouver avec une solution dont le seul mérite est que vous êtes arrivé à la faire tomber en marche (c'est déjà pas si mal... mais vous avez encore des tas de choses à apprendre et comprendre).


    Citation Envoyé par temabul Voir le message
    En fait, même si j'ai mal posé ma question, c'est bien là qu'est mon problème : les créer et leur donner un nom à ces widgets (à partir d'un paramètre).
    Vous avez bien posé la question. Sve@r vous a montré comment faire avec "eval" et nous vous avons suggéré comment s'en passer en utilisant listes et dictionnaires.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par temabul Voir le message
    Mais cela ne fonctionne pas si à la place de __lettres je défini self.lettre = "ABCD" dans le __init__ et bien sûr modifie les différents appels à cet objet.
    Ah bon ?
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import tkinter as tk
     
    class Appli1(tk.Tk):
    	def __init__(self, lettres):
    		super().__init__()
    		self.__lettres = lettres
    		self.__creer_widgets()
     
    	def __creer_widgets(self):
    		self.grid()
    		self.bout = dict(
    			(
    				lettre,
    				tk.Button(
    					self,
    					text=lettre,
    					width="10",
    					height="10",
    					command=lambda i=lettre: self.imprime_lettre(i),
    				),
    			) for lettre in self.__lettres
    		)
    		for (i, lettre) in enumerate(self.__lettres, 1):
    			self.bout[lettre].grid(row=1, column=i)
     
    	def imprime_lettre(self, lettre): print(lettre)
     
    	def change_couleur(self, bouton):
    		self.bout[bouton].configure(bg="yellow")
     
    if __name__ == "__main__":
    	app = Appli1("ABCD")
    	app.change_couleur('B')
    	app.mainloop()

    C'est vrai qu'au premier jet, j'ai mis "__lettres" en tant qu'attribut de classe. Je le voyais comme une pseudo-constante peu évolutive. Mais en effet ça peut parfaitement être un attribut dédié aux instances pourquoi pas. Ca permet de rendre le truc plus modulable.
    Accessoirement tu devrais revoir ta façon de te repérer dans un dictionnaire. Les outils Python (et dans les langages en général) sont dédiés à un besoin spécifique. J'ai utilisé enumerate() parce que j'avais besoin d'avoir en parallèle à la fois le bouton et à la fois un indice commençant à 1 pour pouvoir l'utiliser comme colonne dudit bouton. J'aurais pu ne pas l'utiliser, ne pas le connaitre, être dans un langage qui ne l'implémente pas ; et le remplacer alors par une variable à 1 et l'incrémenter à chaque itération. Tout ça pour dire que dans "creer_widget" j'ai mis en oeuvre un outil parce que j'avais un besoin et que cet outil y répondait. Explique-moi en quoi enumerate() sert à quelque chose pour trouver le bouton demandé dans ta méthode "change_couleur" ?
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre averti Avatar de temabul
    Homme Profil pro
    Informatique de Loisir
    Inscrit en
    Février 2015
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Informatique de Loisir

    Informations forums :
    Inscription : Février 2015
    Messages : 26
    Par défaut
    Oui, ça fonctionne !
    Bonsoir, pour répondre à ta question Sve@r
    Je croyais que les widgets étaient bien créés lors de la 1ère boucle avec énumerate(), mais qu'ils n'avaient pas de nom.
    Quand on crée simplement un bouton on a boutonA = Button(self, text='A', width="10, height="10",command=lambda i=lettre: self.imprime_lettre(i))[/CODE]
    et ce bouton a un nom; boutonA dans ce cas et ça permet de modifier le widget.
    En fait le dictionnaire créé qui a servi à créer et positionné les widgets, existe bien après cette fabrication. C'est ce que je n'avais pas compris. Et c'est pour ça que je refaisais enumerate(). Peut-être mettait-il d'autres boutons par dessus les précédents.

  11. #11
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par temabul Voir le message
    Je croyais que les widgets étaient bien créés lors de la 1ère boucle avec énumerate(), mais qu'ils n'avaient pas de nom.
    Non non non, enumerate() ne sert pas à créer des choses. Ca sert juste à énumérer un itérable (un truc pouvant être traité dans une boucle) c'est à dire donner chaque élément de l'itérable en l'associant à un compteur.
    Quand tu ne sais pas à quoi sert un outil, tu as tout à fait le droit d'ouvrir une console Python (la fenêtre où chaque ligne commence par ">>>") et exécuter l'outil directement voir ce que ça donne. Ensuite tu as le help => help(enumerate)
    Citation Envoyé par temabul Voir le message
    Quand on crée simplement un bouton on a
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     boutonA = Button(self, text='A', width="10, height="10",command=lambda i=lettre: self.imprime_lettre(i))
    et ce bouton a un nom; boutonA dans ce cas et ça permet de modifier le widget.
    Oui, c'est un petit peu une des bases de Python que de pouvoir sauvegarder des "trucs" dans des variables qu'on peut alors réutiliser ensuite. Sauf que si on a plein de trucs similaires (des personnes, des cases d'un jeu, des brins d'ADN, des boutons tk de même nature) on peut les sauvegarder alors dans des containers (des objets permettant de tous les sauvegarder à la fois). Ensuite pour traiter l'un ou l'autre on accède à celui de son choix directement (indice, index) et si on veut tous les traiter d'un coup on passe alors par une boucle.

    Citation Envoyé par temabul Voir le message
    En fait le dictionnaire créé qui a servi à créer et positionné les widgets, existe bien après cette fabrication. C'est ce que je n'avais pas compris. Et c'est pour ça que je refaisais enumerate().
    Tout ce que tu faisais, c'est un truc ressemblant à ceci
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def affiche(n):
    	for (i, x) in enumerate(...tout un ensemble dans lequel il y a n..., 1):
    		if x == n: print(x)

    Déjà donc si "i" n'est pas utilisé, enumerate() ne sert à rien. Ce qui peut alors s'écrire en ceci
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def affiche(n):
    	for x in ...tout un ensemble dans lequel il y a n...:
    		if x == n: print(x)

    Et là, on voit de suite que traiter tout l'ensemble dans lequel il y a "n" pour voir si on a trouvé le "n" à afficher est... con. On reçoit "n" qu'on veut afficher, on l'affiche simplement !!!

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def affiche(n):
    	print(n)

    Citation Envoyé par temabul Voir le message
    Peut-être mettait-il d'autres boutons par dessus les précédents.
    Ouvre un tutoriel et lis-le. Tu ne peux pas continuer à avancer avec toutes ces failles dans les connaissances de base de Python...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  12. #12
    Membre averti Avatar de temabul
    Homme Profil pro
    Informatique de Loisir
    Inscrit en
    Février 2015
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Informatique de Loisir

    Informations forums :
    Inscription : Février 2015
    Messages : 26
    Par défaut
    J'ai encore progressé dans la compréhension.
    Merci pour vos conseils et explications.
    Je considère que le sujet est résolu, par contre pour moi un long chemin me reste à parcourir

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Stocker un objet dans une variable
    Par Arkoze dans le forum Langage
    Réponses: 3
    Dernier message: 17/02/2011, 17h24
  2. [PHP 5.3] Sérialiser et Désérialiser un objet dans une variable de session
    Par hervelyon dans le forum Langage
    Réponses: 1
    Dernier message: 11/05/2010, 20h26
  3. [PHP 5.2] Mettre un objet dans une variable de session ?
    Par kolbek dans le forum Langage
    Réponses: 4
    Dernier message: 10/12/2009, 09h48
  4. utilisation d'un objet dans une variable session
    Par hammag dans le forum Langage
    Réponses: 1
    Dernier message: 28/04/2009, 14h59
  5. Mettre un objet dans une variable de session
    Par dondano dans le forum Langage
    Réponses: 4
    Dernier message: 27/11/2006, 22h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo