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

Tkinter Python Discussion :

Problème pour arréter une boucle avec un bouton


Sujet :

Tkinter Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 7
    Points : 6
    Points
    6
    Par défaut Problème pour arréter une boucle avec un bouton
    Bonjour à tous !

    je commence la programmation et surtout la création d'interfaces graphiques. J'essaie de créer un programme qui permet à l'utilisateur de rentrer des informations sur plusieures personnes puis de l'enregistrer sur un fichier (je n'ai pas encore commencer à coder cette partie).
    Voici le code :
    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
    40
    41
    42
    43
    from tkinter import *
     
    class Infos(Frame):
     
        def perso_suivante(self):
            i += 1
            return i
     
        def __init__(self, boss =None):        
            Frame.__init__(self)
            self.pack()
     
            i = 1
            while i > 0 and i < 5:
                # texte intro
                personne = 'Personne n° ' + str(i)
                self.texteintro = Label(self, text = personne)
                self.texteintro.grid(column = 1, row = 1)
     
                self.txt_nom = Label(self, text = 'Nom :')
                self.txt_nom.grid(column = 1, row = 2, sticky = 'W')
                self.texte_nom = Entry(self)
                self.texte_nom.insert(END, "")
                self.texte_nom.grid(column = 1, row = 3)
     
                # choix : homme ou femme
                self.txt_sexe = Label(self, text  = 'Sexe')
                self.txt_sexe.grid(column = 1, row = 4, sticky = 'W')
                Possibilites =["Homme", "Femme"]
                self.choix = StringVar()
                self.choix.set(Possibilites[1])
                for n in range(2):
                    bout = Radiobutton(self,
                                       text = Possibilites[n],
                                       variable = self.choix,
                                       value = Possibilites[n])
                    bout.grid(row = n + 4, column = 1, sticky = 'W')
     
                self.bouton = Button(self, text = 'Personne suivante', command = self.perso_suivante)
                self.bouton.grid(row = 7, column = 1)
     
    if __name__ == '__main__':
        Infos().mainloop()
    Je souhaiterais suspendre la boucle tant que l'utilisateur n'a pas appuyé sur le bouton. Je voudrais savoir comment il faut s'y prendre pour que le clic sur le bouton entraîne l'incrémentation de i par 1 (je ne sais pas si c'est la bon façon de dire : i += 1 ) et donc qu'il entraine l'entrée de données pour la personne suivante.
    Désolé si je ne suis pas très clair, c'est un peu mélangé dans ma tête ...
    Si quelqu'un pourrait me répondre, cela me serait d'une grande aide ^^
    Merci d'avance

  2. #2
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Pas besoin de while puisque vous avez déjà une boucle : mainloop

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    from tkinter import *
     
     
    class Infos(Frame):
     
        def perso_suivante(self):
            # Enregistrez les données ici (voir .get())
            # et on passe au suivant:
            self.i += 1
            self.texteintro.config(text='Personne n° %d' % self.i)
            self.texte_nom.delete(0, END)
            self.choix.set(self.Possibilites[1])
            if self.i == 5:
                self.bouton.config(state=DISABLED)
     
        def __init__(self, boss =None):        
            Frame.__init__(self)
            self.pack()
     
            self.i = 1
            # texte intro
            personne = 'Personne n° %d' % self.i
            self.texteintro = Label(self, text='Personne n° %d' % self.i)
            self.texteintro.grid(column=1, row=1)
     
            self.txt_nom = Label(self, text='Nom :')
            self.txt_nom.grid(column=1, row=2, sticky='W')
            self.texte_nom = Entry(self)
            self.texte_nom.insert(END, "")
            self.texte_nom.grid(column=1, row=3)
     
            # choix : homme ou femme
            self.txt_sexe = Label(self, text='Sexe')
            self.txt_sexe.grid(column=1, row=4, sticky='W')
            self.Possibilites = ["Homme", "Femme"]
            self.choix = StringVar()
            self.choix.set(self.Possibilites[1])
            for n in range(2):
                bout = Radiobutton(self,
                                   text=self.Possibilites[n],
                                   variable=self.choix,
                                   value=self.Possibilites[n])
                bout.grid(row=n+4, column=1, sticky='W')
     
            self.bouton = Button(self, text='Personne suivante', command=self.perso_suivante)
            self.bouton.grid(row=7, column=1)
     
     
    if __name__ == '__main__':
        Infos().mainloop()
    @+
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Merci beaucoup de la réponse ! Cela m'aide énormément !

  4. #4
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Si cela aide autant rajouter quelques notes.

    Dans votre boucle while vous recréez des Widgets à chaque fois.
    Un exemple simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import tkinter as tk
     
     
    root = tk.Tk()
    i = 0
    while i < 6:  # C'est la même chose avec for i in range(6)
        bout = tk.Button(root, text="Button %d" % i)
        print("Instance: %s Nom: bout Affiche: Button %d" % (bout, i))
        bout.grid(row=0, column=0)  # C'est toujours la même position...
        i += 1
    root.mainloop()
    Et sa sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Instance: .147859212 Nom: bout Affiche: Button 0
    Instance: .148403308 Nom: bout Affiche: Button 1
    Instance: .148429964 Nom: bout Affiche: Button 2
    Instance: .148502412 Nom: bout Affiche: Button 3
    Instance: .148403436 Nom: bout Affiche: Button 4
    Instance: .148563884 Nom: bout Affiche: Button 5
    Ce que cela donne en modifiant la positions des Widgets:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import tkinter as tk
     
     
    root = tk.Tk()
    i = 0
    while i < 6:
        bout = tk.Button(root, text="Button %d" % i)
        print("Instance: %s Nom: bout Affiche: Button %d" % (bout, i))
        bout.grid(row=i, column=0)  # << Ici
        i += 1
    root.mainloop()
    Cela est sans conséquence dans votre code puisque vous utilisez à chaque fois les dernières instances mais comprenez bien que vous n'avez plus accès (pas tout à fait vrais: il existe la possibilité de rechercher les Widgets mais c'est plus compliqué) aux instances dont vous avez 'écraser' le nom sous Python:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import tkinter as tk
     
     
    root = tk.Tk()
    for i in range(6):
        bout = tk.Button(root, text="Button %d" % i)
        print("Instance: %s Nom: bout Affiche: Button %d" % (bout, i))
        bout.grid(row=i, column=0)  # << Ici
    bout.config(state=tk.DISABLED)
    root.mainloop()
    Si vous créez des Widgets dans une boucle et que vous voulez en garder une référence utilisez des boites (listes, dico, etc):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import tkinter as tk
     
     
    root = tk.Tk()
    bouttons = []
    for i in range(6):
        bout = tk.Button(root, text="Button %d" % i)
        bout.grid(row=i, column=0)
        bouttons.append(bout)
    bouttons[1].config(state=tk.DISABLED)  # On travaille ici sur l'index dans la liste
    root.mainloop()
    ou encore:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import tkinter as tk
     
     
    root = tk.Tk()
    bouttons = {}
    for i in range(6):
        bout = tk.Button(root, text="Button %d" % i)
        bout.grid(row=i, column=0)
        bouttons[i] = bout
    bouttons[1].config(state=tk.DISABLED)  # On travaille ici sur la clé du dico
    bouttons[3].config(state=tk.DISABLED)
    root.mainloop()
    Etc...

    A noter que le cas de la création de Button dans une boucle est 'spécial' (de même que les Widgets Checkbutton, Radiobutton, Scale et Scrollbar qui ont l'option 'command' ou encore Entry si l'on utilise la validation) à partir du moment ou seule la fonction contenue dans 'command' nous importes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import tkinter as tk
     
     
    root = tk.Tk()
    lab = tk.Label(root)
    lab.pack()
    for i in range(6):
        bout = tk.Button(root, text="Button %d" % i,
                         command=lambda val=i:
                             lab.config(text="%d selected" % val))
        bout.pack()
    root.mainloop()
    "Pour aller plus loin" (command et lambda):
    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    import tkinter
     
     
    def func(var):
        # print(var)
        display.config(text=str(var))
     
     
    win = tkinter.Tk()
    win.title("command & lambda")
     
    geomopts = {'padx':5, 'pady':5}
     
    codeframe = tkinter.Frame(win)
     
    xscrollbar = tkinter.Scrollbar(codeframe, orient=tkinter.HORIZONTAL)
    xscrollbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
     
    yscrollbar = tkinter.Scrollbar(codeframe)
    yscrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
     
    text = tkinter.Text(codeframe, wrap=tkinter.NONE,
                        xscrollcommand=xscrollbar.set,
                        yscrollcommand=yscrollbar.set)
    text.pack()
     
    xscrollbar.config(command=text.xview)
    yscrollbar.config(command=text.yview)
     
    code = """import tkinter
     
     
    def func(var):
        # print(var)
        display.config(text=str(var))
     
     
    win = tkinter.Tk()
    win.title("command & lambda")
     
    geomopts = {'padx':5, 'pady':5}
     
    codeframe = tkinter.Frame(win)
     
    xscrollbar = tkinter.Scrollbar(codeframe, orient=tkinter.HORIZONTAL)
    xscrollbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
     
    yscrollbar = tkinter.Scrollbar(codeframe)
    yscrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
     
    text = tkinter.Text(codeframe, wrap=tkinter.NONE,
                        xscrollcommand=xscrollbar.set,
                        yscrollcommand=yscrollbar.set)
    text.pack()
     
    xscrollbar.config(command=text.xview)
    yscrollbar.config(command=text.yview)
     
    widgetsframe = tkinter.Frame(win)
     
    display = tkinter.Label(widgetsframe, bd=1, relief=tkinter.SUNKEN, bg='white', fg='red')
    display.grid(row=0, column=0, columnspan=9,
                 sticky=tkinter.W+tkinter.E+tkinter.N+tkinter.S, **geomopts)
     
    tkinter.Label(widgetsframe, text="Whitout lambda",
                  fg='blue').grid(row=1, column=0, **geomopts)
    tkinter.Label(widgetsframe, text="lambda : func(value)",
                  fg='blue').grid(row=1, column=2, **geomopts)
    tkinter.Label(widgetsframe, text="lambda value=value: func(value)",
                  fg='blue').grid(row=1, column=4, **geomopts)
    tkinter.Label(widgetsframe, text="lambda value=staticentry.get(): func(value)",
                  fg='blue').grid(row=1, column=6, **geomopts)
    tkinter.Label(widgetsframe, text="lambda : func(variableentry.get())",
                  fg='blue').grid(row=1, column=8, **geomopts)
     
    for line in range(1, 6):
        tkinter.Button(widgetsframe, text="func %d" % (line),
                       command=func(line)).grid(row=line+2, column=0, **geomopts)
        tkinter.Button(widgetsframe, text="func %d" % (line),
                       command=lambda : func(line)).grid(row=line+2,
                                                         column=2,
                                                         **geomopts)
        tkinter.Button(widgetsframe, text="func %d" % (line),
                       command=lambda line=line: func(line)).grid(row=line+2,
                                                                  column=4,
                                                                  **geomopts)
     
    staticentry = tkinter.Entry(widgetsframe, bd=1, relief=tkinter.SUNKEN,
                                font=("Helvetica", "12", "bold italic"))
    staticentry.grid(row=4, column=6, **geomopts)
    staticentry.insert(0, "Enter text")
    staticentry.bind("<1>", lambda event: staticentry.delete(0, tkinter.END))
    variableentry = tkinter.Entry(widgetsframe, bd=1, relief=tkinter.SUNKEN,
                                  font=("Helvetica", "12", "bold italic"))
    tkinter.Button(widgetsframe, text="Apply text",
                   command=lambda value=staticentry.get(): func(value)).grid(row=5, column=6, **geomopts)
    variableentry.grid(row=4, column=8, **geomopts)
    variableentry.insert(0, "Enter text")
    variableentry.bind("<1>", lambda event: variableentry.delete(0, tkinter.END))
    tkinter.Button(widgetsframe, text="Apply text",
                   command=lambda : func(variableentry.get())).grid(row=5, column=8,
                                                                    **geomopts)
     
    tkinter.Frame(widgetsframe, height=2, bd=1, relief=tkinter.SUNKEN).grid(row=2, column=0, columnspan=9, sticky=tkinter.E+tkinter.W, **geomopts)
    for c in range(1, 9, 2):
        tkinter.Frame(widgetsframe, width=2, bd=1,
                      relief=tkinter.SUNKEN).grid(row=1, column=c, rowspan=7,
                                                  sticky=tkinter.N+tkinter.S,
                                                  **geomopts)
    tkinter.Frame(widgetsframe, height=2, bd=1, relief=tkinter.SUNKEN).grid(row=8, column=0, columnspan=9, sticky=tkinter.E+tkinter.W, **geomopts)
     
    codeframe.grid(row=0, column=0, columnspan=2, **geomopts)
    codeframe.grid_remove()
    widgetsframe.grid(row=0, column=0, columnspan=2, **geomopts)
     
    wb = tkinter.Button(win, text="Widgets",
                        command=lambda: codeframe.grid_remove() or widgetsframe.grid())
    wb.grid(row=1, column=0, **geomopts)
    wc = tkinter.Button(win, text="Code",
                        command=lambda: widgetsframe.grid_remove() or codeframe.grid())
    wc.grid(row=1, column=1, **geomopts)
    tkinter.Frame(win, height=2, bd=1, relief=tkinter.SUNKEN).grid(row=2, column=0, columnspan=9, sticky=tkinter.E+tkinter.W, **geomopts)
    wc = tkinter.Button(win, text="Exit", command=win.destroy)
    wc.grid(row=3, column=0, columnspan=2, **geomopts)
     
    win.mainloop()
    """
    text.insert(tkinter.END, code)
     
    widgetsframe = tkinter.Frame(win)
     
    display = tkinter.Label(widgetsframe, bd=1, relief=tkinter.SUNKEN, bg='white', fg='red')
    display.grid(row=0, column=0, columnspan=9,
                 sticky=tkinter.W+tkinter.E+tkinter.N+tkinter.S, **geomopts)
     
    tkinter.Label(widgetsframe, text="Whitout lambda",
                  fg='blue').grid(row=1, column=0, **geomopts)
    tkinter.Label(widgetsframe, text="lambda : func(value)",
                  fg='blue').grid(row=1, column=2, **geomopts)
    tkinter.Label(widgetsframe, text="lambda value=value: func(value)",
                  fg='blue').grid(row=1, column=4, **geomopts)
    tkinter.Label(widgetsframe, text="lambda value=staticentry.get(): func(value)",
                  fg='blue').grid(row=1, column=6, **geomopts)
    tkinter.Label(widgetsframe, text="lambda : func(variableentry.get())",
                  fg='blue').grid(row=1, column=8, **geomopts)
     
    for line in range(1, 6):
        tkinter.Button(widgetsframe, text="func %d" % (line),
                       command=func(line)).grid(row=line+2, column=0, **geomopts)
        tkinter.Button(widgetsframe, text="func %d" % (line),
                       command=lambda : func(line)).grid(row=line+2,
                                                         column=2,
                                                         **geomopts)
        tkinter.Button(widgetsframe, text="func %d" % (line),
                       command=lambda line=line: func(line)).grid(row=line+2,
                                                                  column=4,
                                                                  **geomopts)
     
    staticentry = tkinter.Entry(widgetsframe, bd=1, relief=tkinter.SUNKEN,
                                font=("Helvetica", "12", "bold italic"))
    staticentry.grid(row=4, column=6, **geomopts)
    staticentry.insert(0, "Enter text")
    staticentry.bind("<1>", lambda event: staticentry.delete(0, tkinter.END))
    variableentry = tkinter.Entry(widgetsframe, bd=1, relief=tkinter.SUNKEN,
                                  font=("Helvetica", "12", "bold italic"))
    tkinter.Button(widgetsframe, text="Apply text",
                   command=lambda value=staticentry.get(): \
                   func(value)).grid(row=5, column=6, **geomopts)
    variableentry.grid(row=4, column=8, **geomopts)
    variableentry.insert(0, "Enter text")
    variableentry.bind("<1>", lambda event: variableentry.delete(0, tkinter.END))
    tkinter.Button(widgetsframe, text="Apply text",
                   command=lambda : func(variableentry.get())).grid(row=5, column=8,
                                                                    **geomopts)
     
    tkinter.Frame(widgetsframe, height=2, bd=1, relief=tkinter.SUNKEN).grid(row=2, \
        column=0, columnspan=9, sticky=tkinter.E+tkinter.W, **geomopts)
    for c in range(1, 9, 2):
        tkinter.Frame(widgetsframe, width=2, bd=1,
                      relief=tkinter.SUNKEN).grid(row=1, column=c, rowspan=7,
                                                  sticky=tkinter.N+tkinter.S,
                                                  **geomopts)
    tkinter.Frame(widgetsframe, height=2, bd=1, relief=tkinter.SUNKEN).grid(row=8, \
        column=0, columnspan=9, sticky=tkinter.E+tkinter.W, **geomopts)
     
    codeframe.grid(row=0, column=0, columnspan=2, **geomopts)
    codeframe.grid_remove()
    widgetsframe.grid(row=0, column=0, columnspan=2, **geomopts)
     
    wb = tkinter.Button(win, text="Widgets",
                        command=lambda: codeframe.grid_remove() or \
                                        widgetsframe.grid())
    wb.grid(row=1, column=0, **geomopts)
    wc = tkinter.Button(win, text="Code",
                        command=lambda: widgetsframe.grid_remove() or \
                                        codeframe.grid())
    wc.grid(row=1, column=1, **geomopts)
    tkinter.Frame(win, height=2, bd=1, relief=tkinter.SUNKEN).grid(row=2, \
        column=0, columnspan=9, sticky=tkinter.E+tkinter.W, **geomopts)
    wc = tkinter.Button(win, text="Exit", command=win.destroy)
    wc.grid(row=3, column=0, columnspan=2, **geomopts)
     
    win.mainloop()
    EDIT: "pour aller plus loin 2"


    Dans votre code vous utilisez une classe Infos qui hérite de Tkinter.Frame.
    Frame est le conteneur par défaut de Tkinter mais en l'utilisant tel quel il vous crée une instance Tk() (la fenêtre) à laquelle vous n'avez pas accès (Pas de nom pour. Là encore il existe des moyens de retrouver l'objet mais ce n'est pas le but ici).
    Sans aller trop loin dans la 'construction':
    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
    from tkinter import *
     
     
    class Infos(Frame):
        def __init__(self, master):        
            Frame.__init__(self)
            self.master = master
            Button(self, text="EXIT", command=self.master.destroy).pack()
            self.pack()
     
     
    if __name__ == '__main__':
        root = Tk()
        Infos(root)
        root.mainloop()

    Pour finir vous n'avez pas besoin de classe ici:
    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
    from tkinter import *
     
     
    POSSIBILITES = ("Homme", "Femme")
     
     
    root = Tk()
    indx = IntVar(value=1)
     
     
    def perso_suivante():
        # Enregistrez les données ici (voir .get())
        # et on passe au suivant:
        indx.set(indx.get() + 1)
        texteintro.config(text='Personne n° %d' % (indx.get()))
        texte_nom.delete(0, END)
        choix.set(POSSIBILITES[1])
        if indx.get() == 5:
            bouton.config(state=DISABLED)
     
     
    personne = 'Personne n° %d' % (indx.get())
    texteintro = Label(root, text='Personne n° %d' % (indx.get()))
    texteintro.grid(column=1, row=1)
    Label(root, text='Nom :').grid(column=1, row=2, sticky='W')
    texte_nom = Entry(root)
    texte_nom.grid(column=1, row=3)
    Label(root, text='Sexe').grid(column=1, row=4, sticky='W')
    choix = StringVar(value=POSSIBILITES[1])
    for n in range(2):
        Radiobutton(root, text=POSSIBILITES[n], variable=choix,
                    value=POSSIBILITES[n]).grid(row=n + 4, column=1, sticky='W')
    bouton = Button(root, text='Personne suivante', command=perso_suivante)
    bouton.grid(row=7, column=1)
    root.mainloop()
    Je sais bien que pas mal de sites proposent une 'initiation' à Tkinter avec des classes (principalement en comparaison à d'autres GUI) mais en soit Tkinter n'en a pas besoin et ce n'est utile que pour Python. Un exemple de code ou une classe est 'utile' : InfoBulle.
    Mélanger l'apprentissage du Wrapper Tkinter et l'apprentissage de la POO est, pour moi, une mauvaise idée.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 4
    Points : 13
    Points
    13
    Par défaut
    Bonjour,

    je me greffe à un sujet déjà existant mais en realité j'ai un probleme lié a ce qui se dit ici


    J'ai une boucle qui me construit des boutons, a chaque boutons je garde l'instance

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bouttons[rang] = button
    et plus tard je l'utilise

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bouttons.config(state='disabled',cursor="arrow")
    J'ai finalement ce code d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dict object has no attribute config
    Si quelqu'un a une idée... merci

  6. #6
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Ben oui...

    'bouttons' est un dico Python qui contient des références à des Widgets Tkinter.

    Nous avons donc :
    bouttons[rang] un objet str (texte) et button un Widget.

    Un objet str n'as pas d'attribut 'config'

    Testez (est comprenez) cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for w in bouttons
        w.config(state='disabled', cursor="arrow")
    @+
    Merci d'utiliser le forum pour les questions techniques.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Moloumo Voir le message
    Bonjour,

    je me greffe à un sujet déjà existant mais en realité j'ai un probleme lié a ce qui se dit ici


    J'ai une boucle qui me construit des boutons, a chaque boutons je garde l'instance

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bouttons[rang] = button
    et plus tard je l'utilise

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bouttons.config(state='disabled',cursor="arrow")
    J'ai finalement ce code d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dict object has no attribute config
    Si quelqu'un a une idée... merci
    Bonjour,

    un objet Python 'dict()' est un dictionnaire qui se compose de paires (clé, valeur).

    Vous pouvez l'écrire ainsi, si c'est plus clair pour vous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    boutons = {
     
       "identifiant1": objet_bouton1,
     
       "identifiant2": objet_bouton2,
     
       "identifiant3": objet_bouton3,
     
    } # fin de boutons
    Ce sont les objets Tkinter (comme les boutons, par ex) qui détiennent la méthode .configure(...).

    Donc si vous voulez appliquer cette méthode à un objet inclus dans votre dictionnaire, vous devez le référencer en propre ou faire une boucle sur les éléments (en anglais: items) du dictionnaire.

    Vous pouvez faire, par exemple :

    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
     
    # récupérer un seul bouton en particulier
     
    mon_bouton = boutons["identifiant3"]   # pas recommandé de faire ça
     
    mon_bouton = boutons.get("identifiant3")   # déjà mieux
     
    # ou alors on boucle sur les paires (clé, valeur)
    # de tous les éléments (items) du dictionnaire
     
    for (_cle, _bouton) in boutons.items():
     
        _bouton.configure(state="disabled", cursor="arrow")   # etc etc
     
    # end for
     
    # et si vous voulez la jouer technique,
    # vous pouvez aussi écrire:
     
    for _bouton in boutons.values():
     
        _bouton.configure(state="disabled", cursor="arrow")   # etc etc
     
    # end for
     
    # mais c'est peut-être moins clair à comprendre...
    @+.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 4
    Points : 13
    Points
    13
    Par défaut
    Merci à vous deux , j'ai bien compris mon erreur

  9. #9
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 298
    Points : 6 778
    Points
    6 778
    Par défaut
    Citation Envoyé par tarball69 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    boutons = {
     
       "identifiant1": objet_bouton1,
     
       "identifiant2": objet_bouton2,
     
       "identifiant3": objet_bouton3,
     
    } # fin de boutons
    Tss, Tss
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    boutons = {"identifiant1": objet_bouton1,
                "identifiant2": objet_bouton2,
                "identifiant3": objet_bouton3,}
    Les conventions syntaxiques sont décrites ici: http://legacy.python.org/dev/peps/pep-0008/

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    mon_bouton = boutons["identifiant3"]   # pas recommandé de faire ça
     
    mon_bouton = boutons.get("identifiant3")   # déjà mieux
    D'où sortent ces recommandations ? ... non recommandables.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Tss, Tss
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    boutons = {"identifiant1": objet_bouton1,
                "identifiant2": objet_bouton2,
                "identifiant3": objet_bouton3,}
    Les conventions syntaxiques sont décrites ici: http://legacy.python.org/dev/peps/pep-0008/


    D'où sortent ces recommandations ? ... non recommandables.
    Bonjour,

    Oui, la PEP 8, je connais merci. Mais ce sont des recommandations, le but étant de rendre le code LISIBLE.

    C'est bien ce que je fais.

    La différence entre dict[key] et dict.get(key) ?

    c'est évident : dans le premier cas, si l'identifiant n'existe pas, on a droit à un beau KeyError alors qu'avec le deuxième cas, une erreur sur clé retourne au pire None.

    Après, c'est à chacun de voir s'il préfère gérer les exceptions partout ou s'il préfère parfois gérer les None en silence (surtout au couvent).

    @+

  11. #11
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 784
    Points : 7 043
    Points
    7 043
    Par défaut
    Eh bien en fait ça dépend, ici il n'y a pas de demande utilisateur et donc aucun besoin de test sur la présence ou non de la clé du dictionnaire.

    Maintenant si on recherche une clé correspondant à la demande d'un utilisateur lambda du programme, ce test peut être fait de cette façon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if key in dict:
        print(dict[key])
    else:
        # exception à gérer
    ou avec la méthode get, et get est très bien dans cette situation...

    Mais l'un n'est pas plus LISIBLE que l'autre, ça c'est certains ! Je dirais que c'est une question de contexte, d'experience et de besoin

    Bonne soirée
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Eh bien en fait ça dépend, ici il n'y a pas de demande utilisateur et donc aucun besoin de test sur la présence ou non de la clé du dictionnaire.

    Maintenant si on recherche une clé correspondant à la demande d'un utilisateur lambda du programme, ce test peut être fait de cette façon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if key in dict:
        print(dict[key])
    else:
        # exception à gérer
    ou avec la méthode get, et get est très bien dans cette situation...

    Mais l'un n'est pas plus LISIBLE que l'autre, ça c'est certains ! Je dirais que c'est une question de contexte, d'experience et de besoin

    Bonne soirée
    LOL c'est un peu le concours de celui qui aura la plus grosse par ici

    Moi, je n'aide pas les autres pour montrer ma science, j'aide les autres en essayant de me mettre à leur hauteur ben en fait... pour les aider

    Ceci dit, en terme de tartinage de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if key in dict:
        print(dict[key])
    else:
        # exception à gérer
    et

    c'est techniquement exactement la même chose : Python fait immanquablement une recherche if key in dict pour sa méthode get().

    La seule différence, c'est qu'au lieu de tartiner 6 ou 7 lignes de code, vous n'en faites qu'une seule.

    En plus, je ne vois pas en quoi ce n'est pas lisible (sauf à me chercher des poux dans la tête à cause de mon statut social, un chômeur qui la ramène, ça fait tache, pas vrai?).

  13. #13
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 784
    Points : 7 043
    Points
    7 043
    Par défaut
    c'est techniquement exactement la même chose : Python fait immanquablement une recherche if key in dict pour sa méthode get().
    Ai-je dis le contraire ? Relisez bien mon précédent post, en aucun cas je dis le contraire, je dis très justement comme tu le dis que get est préférable qu'une grosse tartine...

    Par contre je dis que c'est une question de contexte, pourquoi ?

    La clé est écrite en brut dans le code, il est donc inutile de faire le test de cette clé dans le dictionnaire, on sait qu'elle existe, non?

    En plus, je ne vois pas en quoi ce n'est pas lisible (sauf à me chercher des poux dans la tête à cause de mon statut social, un chômeur qui la ramène, ça fait tache, pas vrai?).
    Ce que je ne vois pas, c'est en quoi c'est plus ou moins lisible en fait ?

    sauf à me chercher des poux dans la tête à cause de mon statut social, un chômeur qui la ramène, ça fait tache, pas vrai?
    Votre remarque me donnait cette impression

    Citation Envoyé par tarball69
    mon_bouton = boutons["identifiant3"] # pas recommandé de faire ça
    Mais j'ai préféré me demander pourquoi vous avez dis cela, plutôt que de jouer à ce petit jeu, bizarrement le contraire a été compris, pas étonnant c'est souvent comme ça! Désolé si vous l'avez mal pris, ce n'était pas mon intention, mais s'il vous plaît, ne me jetez pas vos complexes sous prétexte qu'une remarque ne vous plaise pas, vous valez mieux que cela j'espère, un forum et votre vie, il faut faire la différence, ça ne regarde personne...

    Entre parenthèse, je ne suis pas enseignant en informatique, si ça retire du complexe, j'en suis content pour vous,

    Bonne journée
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Ai-je dis le contraire ? Relisez bien mon précédent post, en aucun cas je dis le contraire, je dis très justement comme tu le dis que get est préférable qu'une grosse tartine...

    Par contre je dis que c'est une question de contexte, pourquoi ?

    La clé est écrite en brut dans le code, il est donc inutile de faire le test de cette clé dans le dictionnaire, on sait qu'elle existe, non?



    Ce que je ne vois pas, c'est en quoi c'est plus ou moins lisible en fait ?



    Votre remarque me donnait cette impression



    Mais j'ai préféré me demander pourquoi vous avez dis cela, plutôt que de jouer à ce petit jeu, bizarrement le contraire a été compris, pas étonnant c'est souvent comme ça! Désolé si vous l'avez mal pris, ce n'était pas mon intention, mais s'il vous plaît, ne me jetez pas vos complexes sous prétexte qu'une remarque ne vous plaise pas, vous valez mieux que cela j'espère, un forum et votre vie, il faut faire la différence, ça ne regarde personne...

    Entre parenthèse, je ne suis pas enseignant en informatique, si ça retire du complexe, j'en suis content pour vous,

    Bonne journée
    Vous avez raison, au temps pour moi.

    Désolé.

    Je ne suis pas là non plus pour m'agacer sur des détails, ni pour flammer, ni pour troller, ni rien de tout ça.

    La discussion sur la lisibilité était portée sur la déclaration bouton = {...} que me reprochait VinsS (c'est son avis, je le respecte comme tel).

    Je crois qu'il y a eu un dérapage incontrôlé ensuite.

    De plus, parfois j'oublie de préciser que je parle d'une manière générale dans mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mon_bouton = boutons["identifiant3"] # pas recommandé de faire ça
    C'est évidemment pas recommandé de faire EN GÉNÉRAL quand on ne connaît pas la clé.

    Bien sûr que si la clé est connue et codée en dur, on peut (on doit?) utiliser plutôt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mon_bouton = boutons["identifiant3"]
    J'ai peut-être le tort de prendre souvent des raccourcis qui manquent de rigueur, je ne sais pas.

    Quant à mon statut de chômeur : ce n'est pas un complexe.

    Partout où je passe, je gêne.

    * quand je travaillais en entreprise, je gênais mes collègues à tout faire dix fois plus vite que les autres : on me laissait parfois une "délicate" attention sur mon bureau pour me rappeler à quel point je faisais le bonheur de mon patron mais pas celui de mes collègues... au bout d'un moment, ça gonfle dru.

    * quand je travaillais en indépendant, je gênais évidemment mes concurrents, mais ça, c'est de bonne guerre... jusqu'à ce qu'ils réussissent à pilonner ma boîte, évidemment.

    * quand je me retrouve au chômage - donc théoriquement hors de toute emmerde prévisible - je me dis : "tiens, faisons un saut voir les fora (forums)" - et là aussi, visiblement je ne suis pas franchement le bienvenu.

    Mais bah, au bout de vingt-cinq ans à me faire haïr de tous côtés, je devrais finir par prendre l'habitude (sauf que je n'y arrive pas, désolé d'exister, nan vraiment).

    Donc, NON, ce n'est pas contre vous que j'en ai, c'est contre la manie de me faire systématiquement reprocher des broutilles quand il y a bien plus important à faire par ailleurs.

    Ok, je ne suis pas un crack de l'enseignement et OUI je dis souvent des conneries, mais comme me disait mon grand-père :

    "C'est en faisant que l'on devient faiseron."

    LOL. Papy t'es trop fort !

  15. #15
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 784
    Points : 7 043
    Points
    7 043
    Par défaut
    Partout où je passe, je gêne.
    Dans un forum ce n'est pas le cas, vous avez autant de droits que n'importe qui, et ce, quelquesoit votre statut personnel, qui d'ailleurs n'est pas forcément censé se savoir.

    Votre remarque m'a interpellé et a affûté ma curiosité dans le sens où une question me turlipinait: Dans quelle documentation officielle ceci est indiquée (je n'ai pas trouvé), alors j'ai essayé d'en voir une logique dans des cas différents (la clé écrite en dur dans le code, et la clé demandée par un utilisateur lambda).


    • On se rend compte que la méthode get est une très bonne idée, lorsque l'utilisateur ne connaît pas le dictionnaire et les clés qu'il contient.
    • On se rend compte de l'inutilité de la méthode get quand on connaît déjà la clé d'un dictionnaire (c'est un test supplémentaire inutile)


    Maintenant comme vous le dîtes, les goûts et les couleurs ça ne se discutent pas, et encore moins pour entre développeurs expérimentés censés lire une documentation et l'utiliser à bon escient.

    Donc, NON, ce n'est pas contre vous que j'en ai, c'est contre la manie de me faire systématiquement reprocher des broutilles quand il y a bien plus important à faire par ailleurs
    C'est pourtant pour cela que je suis sur un forum, j'aime les discutions sur des petits détails, difficiles à chercher et à trouver. Modifier sa façon de voir les choses, ça a du bon, on a pas la science infuse. Un ancien professeur (doctorant) me disait toujours ceci : Ne jamais être d'accord, toujours critiquer, tout se critique, même l'évidence...

    Si on veut progresser, faut titiller, pour cela, tu dois trouver les billes qui te permettent de le prouver, ce que j'ai fais avec toi

    Mais en conclusion, je vous rassure, vous ne gênez pas, il y a de la place pour tout le monde, et chaque expérience est bonne à prendre !

    À bientôt,
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  16. #16
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Dans un forum ce n'est pas le cas, vous avez autant de droits que n'importe qui, et ce, quelquesoit votre statut personnel, qui d'ailleurs n'est pas forcément censé se savoir.

    Votre remarque m'a interpellé et a affûté ma curiosité dans le sens où une question me turlipinait: Dans quelle documentation officielle ceci est indiquée (je n'ai pas trouvé), alors j'ai essayé d'en voir une logique dans des cas différents (la clé écrite en dur dans le code, et la clé demandée par un utilisateur lambda).


    • On se rend compte que la méthode get est une très bonne idée, lorsque l'utilisateur ne connaît pas le dictionnaire et les clés qu'il contient.
    • On se rend compte de l'inutilité de la méthode get quand on connaît déjà la clé d'un dictionnaire (c'est un test supplémentaire inutile)


    Maintenant comme vous le dîtes, les goûts et les couleurs ça ne se discutent pas, et encore moins pour entre développeurs expérimentés censés lire une documentation et l'utiliser à bon escient.



    C'est pourtant pour cela que je suis sur un forum, j'aime les discutions sur des petits détails, difficiles à chercher et à trouver. Modifier sa façon de voir les choses, ça a du bon, on a pas la science infuse. Un ancien professeur (doctorant) me disait toujours ceci : Ne jamais être d'accord, toujours critiquer, tout se critique, même l'évidence...

    Si on veut progresser, faut titiller, pour cela, tu dois trouver les billes qui te permettent de le prouver, ce que j'ai fais avec toi

    Mais en conclusion, je vous rassure, vous ne gênez pas, il y a de la place pour tout le monde, et chaque expérience est bonne à prendre !

    À bientôt,
    Cool !

    • On se rend compte que la méthode get est une très bonne idée, lorsque l'utilisateur ne connaît pas le dictionnaire et les clés qu'il contient.
    • On se rend compte de l'inutilité de la méthode get quand on connaît déjà la clé d'un dictionnaire (c'est un test supplémentaire inutile)


    Perso, je pars du principe qu'à défaut d'être sûr que la clé ne sera pas inconnue à un moment ou à un autre, il vaut mieux préférer la méthode .get().

    Si on est sûr que la clé ne sera jamais supprimée (y compris lors d'une dérivation de classe - voir explication plus bas), alors on s'en sert comme d'un nom de variable.

    De même que l'on utilise :

    en nommant en dur le nom de variable, de même on utilise:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mon_dico["ma_clé"] = "valeur"
    comme si "ma_clé" était en réalité une variable, sauf qu'elle est contenue dans un "paquet" dictionnaire.

    Je ne crois pas qu'il y ait aucune recommandation à ce sujet dans aucune doc, vu que c'est généralement laissé à l'appréciation de chacun(e).

    Pour les dérivations de classe :

    il peut arriver parfois que l'on soit amené à définir un dictionnaire comme membre principal dans une classe :

    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
     
    class XMLBuilder:
     
        ATTRS = {
            "id": None,
            "name": None,
            ...etc...
        }
     
        def __init__ (self, *args, **kw):
     
            ...etc...
     
        # end def
     
    # end class XMLBuilder
    D'expérience, j'ai pu noter deux choses :

    1. si quelqu'un dérive cette classe XMLBuilder, il peut à tout moment redéfinir ATTRS et donc les clés de dictionnaire gérées dans le code de XMLBuilder seront caduques bien qu'elles étaient inscrites en dur dans la classe XMLBuilder de départ ---> moi je gère tout en méthode .get() dans ce contexte.

    2. même si on est parfois forcé de déclarer un dictionnaire en membre principal d'une classe, ce n'est JAMAIS une bonne idée : un dictionnaire dict() est passé par référence non seulement aux sous-classes, mais aussi AUX INSTANCES et là, tout se complique : si vous modifiez quelque chose dans votre dict() dans une instance, vous modifiez aussi les valeurs pour la classe et pour les sous-classes. D'où nécessité de provoquer un shallow copy à chaque instanciation dans __init__().

    Pas toujours simples ces objets Python...

  17. #17
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 784
    Points : 7 043
    Points
    7 043
    Par défaut
    1. si quelqu'un dérive cette classe XMLBuilder, il peut à tout moment redéfinir ATTRS et donc les clés de dictionnaire gérées dans le code de XMLBuilder seront caduques bien qu'elles étaient inscrites en dur dans la classe XMLBuilder de départ ---> moi je gère tout en méthode .get() dans ce contexte.
    Pas si vous utilisez la syntaxe __ATTRS, voir la documentation sur les variables privées...

    2. même si on est parfois forcé de déclarer un dictionnaire en membre principal d'une classe, ce n'est JAMAIS une bonne idée : un dictionnaire dict() est passé par référence non seulement aux sous-classes, mais aussi AUX INSTANCES et là, tout se complique : si vous modifiez quelque chose dans votre dict() dans une instance, vous modifiez aussi les valeurs pour la classe et pour les sous-classes. D'où nécessité de provoquer un shallow copy à chaque instanciation dans __init__().
    Et non, comme dis dans ma réponse du petit 1.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  18. #18
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Pas si vous utilisez la syntaxe __ATTRS, voir la documentation sur les variables privées...



    Et non, comme dis dans ma réponse du petit 1.
    Oui, je connais la syntaxe des "protected _identifier" et "private __identifier", mais ce dont je vous parle, c'est de PERMETTRE la dérivation (parce que c'est pertinent de dériver ces membres dans certains cas) MAIS d'en tenir compte dans le code qu'on implémente à un moment donné dans la classe.

    Ce n'est pas une question de protection de données, je veux qu'on puisse modifier a posteriori. C'est une prise de risques calculée.

    J'appelle cela de la programmation "incertaine" mais pas "incohérente" car parfois pertinente, malgré tout.

    LOL

Discussions similaires

  1. Problème pour lancer une application avec Java
    Par bintij dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 23/10/2011, 21h49
  2. [XL-2003] Probléme pour ecrire une macro avec Combobox et incrementation dans plusieurs colonne
    Par mimil49 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 06/07/2011, 11h28
  3. problème pour separer une table avec une procedure
    Par mathieu38 dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 09/04/2009, 10h25
  4. [VBA-E] Problème pour faire une boucle dans une userform
    Par Garlim dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 03/05/2007, 00h10
  5. [VBA-E] Problème pour coder une boucle
    Par lord-asriel dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 04/03/2007, 11h10

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