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 :

object has no attribute


Sujet :

Python

  1. #1
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2010
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Transports

    Informations forums :
    Inscription : Octobre 2010
    Messages : 24
    Par défaut object has no attribute
    Bonsoir,

    (l'exemple est construit avec un widget tkinter, mais le problème est général)

    Pourriez-vous m'expliquer pourquoi une méthode s'applique à un widget 'natif', mais pas à une instance d'une classe fondée sur ce widget?
    - le message indique "has no attribute" alors qu'il s'agit d'une méthode

    voici mon 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
     
    from tkinter import *
     
    fenetre = Tk()
     
    ## CLASSE
    class Champ():
     
        def __init__(self):
     
            self = Label(fenetre, text = "label02 (class Champ)")
            self.grid(row = 1)
     
    # 1
    label01 = Label(fenetre, text = "label01 (widget 'natif')")
    label01.grid(row = 0)
    print("Texte:", label01.cget("text"))
     
    # 2
    label02 = Champ()
    print("Texte:", label02.cget("text"))
     
    fenetre.mainloop()
    Merci!

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Citation Envoyé par jabal64 Voir le message
    Pourriez-vous m'expliquer pourquoi une méthode s'applique à un widget 'natif', mais pas à une instance d'une classe fondée sur ce widget?
    Pour que les attributs de Label se retrouvent dans Champ, il faudrait (par exemple) que Champ "hérite" de Label. Ce qui commence par écrire "class Champ(Label)".
    Revoyez les chapitres adhoc dans votre tuto préféré.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2010
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Transports

    Informations forums :
    Inscription : Octobre 2010
    Messages : 24
    Par défaut
    Merci Wiztricks pour la réponse rapide.

    - j'active le constructeur de la classe mère dans le constructeur de ma classe pour hériter de ses attributs et propriétés.

    dans le code ci-dessous, je ne parviens toujours pas à changer l'attribut (ici 'relief') du widget hérité, alors que ça fonctionne très bien sur le widget 'natif'
    (j'ai essayé avec et sans variable de contrôle tkinter - j'ai laissé en commentaire mes essais)

    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
     
    """
    widget hérité de la classe tkinter "Button"
    intervention sur son RELIEF
     
    - widget 'natif': OK
    - widget hérité: HS:
    le bouton apparaît (tous les attributs de Button sont hérités)
    la méthode 'bascule' s'effectue
    'relief' est modifié, mais l'aspect du bouton ne change pas!?
     
    """
    from tkinter import *
     
    fenetre = Tk()
     
    ## CLASSE
    class Bouton(Button):
     
        def __init__(self):
     
            Button.__init__(self) # active le constructeur de la classe mère 'Button'
     
            self.varTexte = StringVar()
            self.varTexte.set("RAISED")
     
            self = Button(fenetre, relief = RAISED, text = self.varTexte, bg = "green", \
                      width = 20, height = 5, bd = 10, font = ("Times", 16, "bold"),  \
                      command = self.bascule)
            self.grid()
     
     
     
        def bascule(self):
     
            if self["relief"] == SUNKEN:
                self.varTexte.set("RAISED")
    #            self["relief"] = RAISED
    #            self["text"] = "RAISED"
    #            self["bg"] = "green"
    #            self.configure(relief = RAISED, text = "RAISED", bg = "green")
            else:
                self.varTexte.set("SUNKEN")
    #            self["relief"] = SUNKEN
    #            self["text"] = "SUNKEN"
    #            self["bg"] = "red"
    #            self.configure(relief = SUNKEN, text = "SUNKEN", bg = "red")
     
            print("le bouton a été pressé: ", self["relief"], self["text"], self["bg"])
     
    # instanciation
    bouton01 = Bouton()
     
    fenetre.mainloop()
    Merci!

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Lorsque vous écrivez:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
           Button.__init__(self) # active le constructeur de la classe mère 'Button'
     
            self.varTexte = StringVar()
            self.varTexte.set("RAISED")
     
            self = Button(fenetre, relief = RAISED, text = self.varTexte, bg = "green", \
                      width = 20, height = 5, bd = 10, font = ("Times", 16, "bold"),  \
                      command = self.bascule)
    vous avez fabriqué 2 objets Button.
    Lequel est le "bon"? Pourquoi assigner quelque chose à "self"?
    Si c'est dans votre "tuto", changez en rapidement.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2010
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Transports

    Informations forums :
    Inscription : Octobre 2010
    Messages : 24
    Par défaut
    C'est mieux comme ça? Je n'instancie qu'un seul objet de ma classe, n'est-ce pas?
    mon bouton reste obstinément vert alors que la méthode encapsulée est appelée!

    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
     
    from tkinter import *
    fenetre = Tk()
     
    class Bouton(Button):
     
        def __init__(self):
     
            Button.__init__(self) # active le constructeur de la classe mère 'Button'
     
            Button(fenetre, relief = RAISED, text = "RAISED", bg = "green", \
                      width = 20, height = 5, bd = 10, font = ("Times", 16, "bold"),  \
                      command = self.bascule)\
                      .grid()
     
        def bascule(self):
     
            if self["relief"] == SUNKEN:
                self.configure(relief = RAISED, text = "RAISED", bg = "green")
            else:
                self.configure(relief = SUNKEN, text = "SUNKEN", bg = "red")
     
            print("le bouton a été pressé: ", self["relief"], self["text"], self["bg"])
     
    # instanciation
    bouton01 = Bouton()
     
    fenetre.mainloop()
    Merci !

    PS: j'épluche mes tutoriels Python ( Apprendre à programmer avec Python 3 par Gérard Swinnen )

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Citation Envoyé par jabal64 Voir le message
    C'est mieux comme ça? Je n'instancie qu'un seul objet de ma classe, n'est-ce pas?
    Certes mais, in fine, vous aurez construit 2 instances de "Button".
    Relisez votre code! ligne 25:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    # instanciation
    bouton01 = Bouton()
    Et d'une instance de Button.
    Puis, dans le constructeur de Bouton (ligne11):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            Button(fenetre, relief = RAISED, text = "RAISED", bg = "green", \
                      width = 20, height = 5, bd = 10, font = ("Times", 16, "bold"),  \
                      command = self.bascule)\
                      .grid()
    Appeler Button fabrique un autre Button (et de deux).
    La bound method self.bascule sera appelée lorsqu'on click dessus.
    Mais le, self auquel va s'appliquer "bascule" est le premier Button: celui que vous avez s/classé en Bouton.

    Pas besoin de sous-classer pour faire çà:
    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
    import tkinter as tk
     
    def bascule(btn):
        if btn["relief"] == 'sunken':
            btn.configure(relief='raised', text='RAISED', bg = 'green')
        else:
            btn.configure(relief='sunken', text = "SUNKEN", bg = 'red')
        print("le bouton a été pressé: ", btn["relief"], btn["text"], btn["bg"])
     
    app = tk.Tk()
    _default = dict(relief='raised', text='RAISED', bg = 'green',
           width = 20, height = 5, bd = 10, font = ("Times", 16, "bold"))
    btn = tk.Button(app, _default)
    btn['command'] = lambda b=btn: bascule(b)
    btn.grid()
    app.mainloop()
    Il n'est pas interdit de spécialiser Button mais c'est juste créer une boîte pour y placer des trucs dedans:
    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
    import tkinter as tk
     
    def bascule(btn):
        if btn["relief"] == 'sunken':
            btn.configure(relief='raised', text='RAISED', bg = 'green')
        else:
            btn.configure(relief='sunken', text = "SUNKEN", bg = 'red')
        print("le bouton a été pressé: ", btn["relief"], btn["text"], btn["bg"])
     
    class Button(tk.Button):
        _default = dict(relief='raised', text='RAISED', bg = 'green',
               width = 20, height = 5, bd = 10, font = ("Times", 16, "bold"))
        def __init__(self, master=None):
            super().__init__(master, self._default, command=self.bascule)
        bascule = bascule
     
    app = tk.Tk()
    btn = Button()
    btn.grid()
    app.mainloop()
    notez:
    - le "bascule = bascule" qui déclare l'objet fonction "bascule" comme méthode de la nouvelle classe... juste pour illustrer le fonctionnement de "self"
    - l'intérêt de faire import "tkinter as tk": on peut appeler sa classe Button!
    - le nombre de lignes supplémentaires pour juste dire "super! je fais de la POO".

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

  7. #7
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2010
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Transports

    Informations forums :
    Inscription : Octobre 2010
    Messages : 24
    Par défaut
    Merci beaucoup de votre patience!

    Je vais consacrer le temps nécessaire à exploiter votre réponse et à la transposer pour mon projet (un formulaire de saisie)

    Je considère que vous avez résolu mon problème.


    JB

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

Discussions similaires

  1. 'module' object has no attribute 'maketrans'
    Par julien.63 dans le forum Général Python
    Réponses: 3
    Dernier message: 16/05/2009, 20h48
  2. Ftp : 'str' object has no attribute 'read'
    Par noquioz dans le forum Réseau/Web
    Réponses: 3
    Dernier message: 02/01/2009, 15h46
  3. x object has no attribute y (PyQ4t et QLineEdit)
    Par EricStib dans le forum PyQt
    Réponses: 9
    Dernier message: 23/10/2008, 23h00
  4. Probleme : AttributeError: 'tuple' object has no attribute
    Par MrGecko dans le forum Général Python
    Réponses: 1
    Dernier message: 27/05/2007, 09h59
  5. Réponses: 2
    Dernier message: 26/05/2006, 14h48

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