Partage
  • Partager sur Facebook
  • Partager sur Twitter

Erreur de variables

    28 novembre 2016 à 18:05:19

    Bonjour,

    Je code un jeu du pendu dans une fenêtre avec tkinter, en utilisant des images.

    Mais lorsque j'exécute le code, j'obtients ça :

    Traceback (most recent call last):

      File "<string>", line 420, in run_nodebug

      File "<module1>", line 101, in <module>

      File "<module1>", line 74, in affichemot

      File "<module1>", line 66, in affichemot

    AttributeError: 'function' object has no attribute 'upper'

    Pourtant le code m'a l'air bon ?

    # Créé par Mazzeo Roberto, le 08-11-2016 en Python 3.4
    from tkinter import *
    from random import *
    
    # Fonctions utiles
    def trouvermot() :       # Le fichier 'liste.txt' comporte 881 mots
        nbr = randint(1,881)   # Cette fonction choisit un mot au hasard parmi les 881 mots présents
        i = 0
        fichier = open("G:\\Python\\Livre\\Images\\Projet 5\\liste.txt","r")
        while i != nbr :
            mot = fichier.readline().replace("\n","")
            i = i + 1
        if len(mot) < 5 :     # Mais le mot choisit doit être composé de plus de 5 lettres, sinon c'est trop facile à trouver
            while i != nbr :
                mot = fichier.readline().replace("\n","")
                i = i + 1
        fichier.close()
        return mot.upper()
    
    def affichemot(mot,lettre):
        # Première partie de la fonction
        global nbessais     # La première partie actualise l'image du pendu en fonction du nombre d'essais restants du joueur
        nbessais = nbessais - 1   # A chaque clic sur le bouton "proposer" (voir ligne 102), le nombre d'essais restant diminue
        if nbessais == 8 :
            img1 = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme1.gif")   # L'image convenant au nombre d'essais restant est affichée
            Canv.itemconfig(ImagePendu, image = img1)
            Canv.update()
        elif nbessais == 7 :
            img2 = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme2.gif")
            Canv.itemconfig(ImagePendu, image = img2)
            Canv.update()
        elif nbessais == 6 :
            img3 = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme3.gif")
            Canv.itemconfig(ImagePendu, image = img3)
            Canv.update()
        elif nbessais == 5 :
            img4 = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme4.gif")
            Canv.itemconfig(ImagePendu, image = img4)
            Canv.update()
        elif nbessais == 4 :
            img5 = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme5.gif")
            Canv.itemconfig(ImagePendu, image = img5)
            Canv.update()
        elif nbessais == 3 :
            img6 = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme6.gif")
            Canv.itemconfig(ImagePendu, image = img6)
            Canv.update()
        elif nbessais == 2 :
            img7 = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme7.gif")
            Canv.itemconfig(ImagePendu, image = img7)
            Canv.update()
        elif nbessais == 1 :     # Lorsque le joueur atteind le dernier essai, il a perdu
            img8 = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme8.gif")
            Canv.itemconfig(ImagePendu, image = img8)
            Canv.update()
            ecriture.config(text = "Vous avez perdu !")     # Le Label 'ecriture' est actualisé
            EssaisRestant.place_forget()    # Les widgets devenus inutiles sont supprimés
            EntreeProp.place_forget()
            ValidationProp.place_forget()
        EssaisRestant.config(text = "Il vous reste " + str(nbessais) + " essais")   # Ce label donne le nombre
                                                                                    # d'essais qu'il reste au joueur
                                                                                    # (actualisé à chaque clic sur le bouton "proposer")
        # Deuxième partie de la fonction
        r = ""
        for i in range(len(mot)) :   # Affichage du mot au fur et a mesure que le joueur donne ses propositions de lettres
            if lettre.upper().count(mot.upper()[i]) > 0 :
                r = r.upper() + mot.upper()[i] + " "
            else :
                r = r.upper() + "_" + " "
        if lettre.upper() not in mot.upper() :      # Le programme dit si la lettre est ou non dans le mot
            ecriture.config(text = "La lettre '" + lettre.upper() + "' n'est pas dans le mot")
        else :
            ecriture.config(text = "La lettre '" + lettre.upper() + "' est pas dans le mot !")
            AffichageMot.config(text = affichemot(mot, EntreeProp.get))
        return r
    
    fen = Tk()     # Création de la fenêtre, avec options
    fen.title("Jeu du pendu")
    fen.geometry("800x400")
    fen.resizable(width = False, height = False)
    
    nbessais = 9       # Déclaration des variables
    mot = trouvermot()
    aidemot = mot[0]
    
    Canv = Canvas(fen, width = 1500, height = 720, bg = "#3E3F3F")     # Création du Canvas
    Canv.place(x = -2, y = -2)
    
    img = PhotoImage(file = "G:\\Python\\Livre\\Images\\Projet 5\\bonhomme1.gif")   # Affichage du bonhomme pendu au départ
    ImagePendu = Canv.create_image(450, 50, image = img, anchor = 'nw')
    
    EntreeProp = Entry(fen, width = 10)      # Création de l'entrée pour entrer la proposition
    EntreeProp.place(x = 100, y = 250)
    EntreeProp.focus()   # Force le curseur a être dans l'entry 'EntreeProp' pour que le joueur n'ai pas besoin de cliquer dessus
    
    ecriture = Label(fen, text = "Entrez une lettre", font = ("Arial", 20), bg = "#3E3F3F", fg = "White")
    ecriture.place(x = 40, y = 140 )
    EssaisRestant = Label(fen, text = "Il vous reste " + str(nbessais) + " essais", bg = "#3E3F3F", fg = "White")  # Création des labels utiles
    EssaisRestant.place(x = 150, y = 350)
    AffichageMot = Label(fen, font=("Arial", 20), bg="#3E3F3F", fg="White")
    AffichageMot["text"] = affichemot(mot, aidemot)
    AffichageMot.place(x=100, y=50)
    
    ValidationProp = Button(fen, text = "Proposer", command = lambda : affichemot(mot, EntreeProp.get))    # Création du bouton pour confirmer la proposition
    ValidationProp.place(x = 210, y = 246)
    
    fen.mainloop()



    Merci !

    -
    Edité par I-Scryper 29 novembre 2016 à 19:23:55

    • Partager sur Facebook
    • Partager sur Twitter
      28 novembre 2016 à 18:20:00

      C'est EXACTEMENT la même erreur que dans l'un de tes précédents sujet o_O

      La fonction affichemot utilise la variable EssaisRestant. Or cette variable est définies en ligne 96 ALORS QUE tu exécutes la fonction en ligne 94, donc avant la création de la variable (d'où l'erreur).

      -
      Edité par Olygrim 28 novembre 2016 à 18:21:42

      • Partager sur Facebook
      • Partager sur Twitter
      Précepte: Le mieux est l'ennemi du bien
        28 novembre 2016 à 18:26:15

        J'ai inversé mais maintenant j'obtiens ça :

        Traceback (most recent call last):

          File "<string>", line 420, in run_nodebug

          File "<module1>", line 96, in <module>

          File "<module1>", line 74, in affichemot

        NameError: name 'AffichageMot' is not defined

        • Partager sur Facebook
        • Partager sur Twitter
          28 novembre 2016 à 20:27:32

          C'est la même erreur, mais en plus subtile ;).

          Pour la corriger, je te conseille de faire l'affichage du texte en deux étapes:

          AffichageMot = Label(fen, font=("Arial", 20), bg="#3E3F3F", fg="White")
          AffichageMot["text"] = affichemot(mot, aidemot)
          AffichageMot.place(x=100, y=50)
          • Partager sur Facebook
          • Partager sur Twitter
          Précepte: Le mieux est l'ennemi du bien
            28 novembre 2016 à 21:16:04

            Euh, je crois que mon IDE me fait la gueule :lol:

            J'ai modifié et j'ai obtenu ça (encore) :

            Traceback (most recent call last):

              File "<string>", line 420, in run_nodebug

              File "<module1>", line 95, in <module>

              File "<module1>", line 60, in affichemot

            NameError: name 'EssaisRestant' is not defined

            • Partager sur Facebook
            • Partager sur Twitter
              29 novembre 2016 à 4:10:22

              Ouais, encore la même erreur...

              T'as pas envie de revoir les bases de la portée des variables ?

              • Partager sur Facebook
              • Partager sur Twitter

              Blond, bouclé, toujours le sourire aux lèvres...

                29 novembre 2016 à 6:37:37

                J'ai actualisé le code, j'ai encore du apporter quelques modifications et j'obtient ça :

                Traceback (most recent call last):

                  File "<string>", line 420, in run_nodebug

                  File "<module1>", line 101, in <module>

                  File "<module1>", line 74, in affichemot

                  File "<module1>", line 66, in affichemot

                AttributeError: 'function' object has no attribute 'upper'

                Est-ce que ça veut dire que en python 3.4, on peut plus mettre cette fonction dans une autre fonction ?

                J'ai aussi cette erreur dans un autre projet avec la fonction sound.play()

                -
                Edité par I-Scryper 29 novembre 2016 à 19:27:11

                • Partager sur Facebook
                • Partager sur Twitter
                  1 décembre 2016 à 16:38:34

                  Si possible, essaie de mettre à la suite ton nouveau problème (plutôt que de mettre à jour le 1er message) car ça rend la lecture du sujet un peu complexe (les réponses ne répondant plus à la question posée). Ça permet également de suivre l'évolution du sujet (questions/réponses) et aussi ça permet d'être notifié quand tu écris un nouveau message (ce qui n'est pas le cas quand tu édites). Et puis je trouve ça un peu chiant de devoir remonter dans la file des messages :p.

                  Donc concernant ton nouveau problème, tu appelles en ligne 74 la fonction affichemot avec comme argument EntreeProp.get:

                  AffichageMot.config(text = affichemot(mot, EntreeProp.get))


                  Qui est une fonction (car tu n'as pas mis les parenthèses à la méthode get). Donc si tu veux récupérer la valeur, il faut les mettre:

                  AffichageMot.config(text = affichemot(mot, EntreeProp.get()))


                  Reste à savoir si c'est ça que tu voulais faire?

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Précepte: Le mieux est l'ennemi du bien
                    1 décembre 2016 à 16:45:49

                    Non, ce message d'erreur veut dire qu'on ne peut pas appeler la méthode upper sur un objet qui est une fonction.

                    Ça veut dire que dans ton code ligne 66, la variable lettre ou la variable mot (ou les deux) est une fonction au lieu d'une chaine de caractères comme tu le pense.

                    Au passage ta fonction affichemot est compliquée et longue, ce serait pas mal de la découper en fonctions, et de simplifier les lignes 23 à 55 qui peuvent être réduites à 3 ou 4 lignes en utilisant un dictionnaire.

                    -
                    Edité par LoupSolitaire 1 décembre 2016 à 16:47:50

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Blond, bouclé, toujours le sourire aux lèvres...

                      1 décembre 2016 à 19:33:07

                      LoupSolitaire a écrit:

                      Ça veut dire que dans ton code ligne 66, la variable lettre ou la variable mot (ou les deux) est une fonction au lieu d'une chaine de caractères comme tu le pense.

                      Tu as raison, regardes ligne 83 :

                      mot = trouvermot()

                      J'arrange comment ça du coup ? 

                      LoupSolitaire a écrit:

                      Au passage ta fonction affichemot est compliquée et longue, ce serait pas mal de la découper en fonctions, et de simplifier les lignes 23 à 55 qui peuvent être réduites à 3 ou 4 lignes en utilisant un dictionnaire.

                      Je ne manipule pas encore super bien les dictionnaires, mais j'y penserais quand j'aurais fini ce projet et bien pris en main les dictionnaires.

                      Olygrim a écrit:

                      Reste à savoir si c'est ça que tu voulais faire?

                      Non, haha. Mais LoupSolitaire à compris

                      Mais je testerai ça plus tard et je dirais si j'obtient une erreur ou pas ?







                      -
                      Edité par I-Scryper 1 décembre 2016 à 19:35:01

                      • Partager sur Facebook
                      • Partager sur Twitter
                        1 décembre 2016 à 21:39:28

                        Non, LoupSolitaire et moi disons des choses complémentaires.

                        Ta fonction affichemot prend deux arguments (ligne 20) qui doivent être des chaînes de caractères car tu utilises dessus la méthode upper (ligne 66 à 73) (ce que dit LoupSolitaire). Mais en ligne 74, tu utilises ta fonction avec comme argument EntreeProp.get qui est une fonction et non une chaîne de caractère (ce que je dis). Donc la solution est de mettre les parenthèses à la méthode get (ce que tu as sûrement oublier de faire) pour récupérer la valeur de l'Entry.

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Précepte: Le mieux est l'ennemi du bien
                          1 décembre 2016 à 23:55:23

                          Le problème n'est pas ligne 83, Olygrim a bien identifié le problème.

                          Par contre, je l'ai peut-être déjà dit, mais il te manque des bases. Je pense pas que ce soit pertinent de jouer avec les interfaces graphiques sans avoir ces bases.

                          Par exemple, le fait de ne pas maîtriser les structures de données de base, que tu ne fasse pas la différence entre fonction exécutée et fonction passée en argument, que tu ne saches pas faire du debug de base avec print, et que tu ne comprenne pas bien les erreurs affichées par python.

                          Les deux dernières lacunes étant les plus bloquantes. Concentre toi là dessus sinon tu ne peux pas progresser.

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Blond, bouclé, toujours le sourire aux lèvres...

                            2 décembre 2016 à 7:18:28

                            LoupSolitaire a écrit:

                            Par exemple, le fait de ne pas maîtriser les structures de données de base, que tu ne fasse pas la différence entre fonction exécutée et fonction passée en argument, que tu ne saches pas faire du debug de base avec print, et que tu ne comprenne pas bien les erreurs affichées par python.


                            Pour la structure de base, je ne savais pas. Je sais bien qu'il me manque des bases, je fais de mon mieux. Le debug de base, je sais le faire mais je n'ai pas pris l'habitude. Et les erreurs, je demande seulement pour celle que je ne comprends pas et celle que je comprends. Mais que je n'arrive pas à corriger. J'ai plusieurs dizaines de programmes, j'ai eu beaucoup d'erreurs que j'ai su corriger même si c'est vrai que je poste beaucoup et souvent sur OC. Mais merci quand même pour ton conseil.

                            LoupSolitaire a écrit:

                            Le problème n'est pas ligne 83, Olygrim a bien identifié le problème.

                            Je pensais qu'il était là vu que je dis que mot = trouvermot(). Mais donc je dois juste rajouter les parenthèses a mon get et ce ne sera plus considéré comme une fonction ?



                            -
                            Edité par I-Scryper 2 décembre 2016 à 15:14:21

                            • Partager sur Facebook
                            • Partager sur Twitter
                              2 décembre 2016 à 17:39:47

                              I-Scryper a écrit:

                              Mais donc je dois juste rajouter les parenthèses a mon get et ce ne sera plus considéré comme une fonction ?

                              Il y a deux choses à distinguer. La fonction elle-même (qui correspond à son nom) et ce que renvoie la fonction (quand on lui accole les parenthèses):

                              print  #La fonction
                              print("hello")  # -> None: ce que renvoie la fonction
                              
                              min  #la fonction
                              min([2, 6, 9, 1])  # -> 1: ce que renvoie la fonction
                              
                              
                              def mon_addition(x, y):
                                  return x + y  #ce qui sera récupéré lors de l'appel
                              
                              mon_addition  #la fonction
                              mon_addition(3, 4)  # -> 7: ce que renvoie la fontion


                              Autrement dit, il y a ce qu'on appelle le callable (qui est le nom de la fonction) et il y a le ou les valeurs renvoyée(s) par la fonction (qui dépendent entièrement de la fonction elle-même). Pour récupérer ce qu'elle renvoie, il suffit d'ajouter les parenthèses et les éventuels arguments au callable.

                              Dans le cas d'un Entry, la méthode get permet de récupérer ce qu'à écrit l'utilisateur au format chaîne de caractère (c'est l'équivalent graphique de notre input):

                              my_entry.get  #la méthode
                              my_entry.get()  #ce que renvoie la méthode


                              Mais get est également une méthode des variables tkinter et ce qu'on récupère dépend de la classe utilisée:

                              v1 = tk.StringVar()
                              v2 = tk.IntVar()
                              v3 = tk.BooleanVar()
                              v4 = tk.DoubleVar()
                              
                              #La fonction
                              v1.get
                              v2.get
                              v3.get
                              v4.get
                              
                              #ce que renvoie la fonction
                              v1.get()  # -> une chaîne
                              v2.get()  # -> un entier
                              v3.get()  # -> un booléen
                              v4.get()  # -> un flottant

                              -
                              Edité par Olygrim 2 décembre 2016 à 17:43:02

                              • Partager sur Facebook
                              • Partager sur Twitter
                              Précepte: Le mieux est l'ennemi du bien
                                3 décembre 2016 à 21:37:32

                                Merci,

                                J'ai modifié le code, et je l'ai encore modifié plusieurs fois après pour des erreurs semblables à celles du haut du topic.

                                Mais cette fois j'obtient une erreur que je n'ai jamais rencontrée et que je ne comprends pas :

                                  File "<module1>", line 73, in affichemot

                                  File "<module1>", line 59, in affichemot

                                  File "C:\Users\xxxxx\Desktop\Florian\EduPython\App\lib\tkinter\__init__.py", line 1324, in configure

                                    return self._configure('configure', cnf, kw)

                                  File "C:\Users\xxxxx\Desktop\Florian\EduPython\App\lib\tkinter\__init__.py", line 1308, in _configure

                                    cnf = _cnfmerge((cnf, kw))

                                  File "C:\Users\xxxxx\Desktop\Florian\EduPython\App\lib\tkinter\__init__.py", line 99, in _cnfmerge

                                    elif isinstance(cnfs, (type(None), str)):

                                RuntimeError: maximum recursion depth exceeded while calling a Python object

                                (La ligne 'File "<module1>", line 73, in affichemot' apparaît plus de 1000 fois !) 

                                Elle signifie quoi ?

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  4 décembre 2016 à 1:26:32

                                  Ta fonction affichemot s'appelle elle-même à l'infini, elle ne termine jamais.
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Blond, bouclé, toujours le sourire aux lèvres...

                                    4 décembre 2016 à 15:27:42

                                    Comment ça se fait ? Parce que j'obtiens ça dès l'exécution du code, la fenêtre n'est même pas entièrement construite que j'obtiens ça...
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      4 décembre 2016 à 16:27:23

                                      Parce que tu exécute affichemot avant que la fenêtre soit construite, tout simplement !

                                      Ligne 101, tu lances l'exécution, ensuite tout se passe bien jusqu'à la ligne 74, qui exécute à nouveau la fonction, puis on arrive à la ligne 74, qui exécute encore la fonction, puis on arrive à la ligne 74...

                                      Tu vois le principe ?

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Blond, bouclé, toujours le sourire aux lèvres...

                                        4 décembre 2016 à 19:21:00

                                        Ah oui je vois, mais j'arrange ça comment ?

                                        Je découpe ça en deux fonctions ? Une pour la gestion des images que j'appelle à la fin d'une fonction qui s'occupe de la MàJ du label AffichageMot ?

                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        Erreur de variables

                                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                        • Editeur
                                        • Markdown