Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Python] Appel au __str__ d'un objet depuis autre classe

<questionSimple.QuestionSimple instance at 0x01D535A8>

Sujet résolu
15 février 2010 à 21:59:24

Bonsoir.

Je suis confronté à un problème avec la fonction __str__ ...
Je vous explique. J'ai deux classes, une qui s'appelle Quizz, l'autre qui s'appelle QuestionSimple.
Je veux redéfinir la méthode __str__ de Quizz pour qu'elle affiche toutes les questions de l'objet Quizz.

Si je fais le print depuis le fichier questionSimple.py, ça marche:
# -*- coding: cp1252 -*-
class QuestionSimple(Question):
#Du code
#...
#...
    def __str__(self):
        return self.enonce + "\n\t" + self.reponse

if __name__ == "__main__":
    test = QuestionSimple("Qui a ecrit dune?", "Frank Herbert")
    print test

Qui a ecrit dune?
        Frank Herbert


Par contre, si je le fais depuis quizz.py, ça ne marche pas:
# -*- coding: cp1252 -*-
from questionSimple import QuestionSimple
from questionChoixMultiple import QuestionChoixMultiple

class Quizz:
#Du code
#...
#...
    def __str__(self):
        retour = "Quizz :" + self.nom + "\n"
        for index, question in enumerate(self.questions):
            retour += "\n Question n°"+ str(index+1) + ":\n"
            retour += str(question)
        return retour
    
if __name__ == "__main__":     
    test = Quizz("livres")
    print test


Quizz :livres

 Question n°1:
<questionSimple.QuestionSimple instance at 0x039AE738>
 Question n°2:
<questionSimple.QuestionSimple instance at 0x039BBAF8>
 Question n°3:
<questionChoixMultiple.QuestionChoixMultiple instance at 0x039AE850>


J'ai beau chercher, je vois pas d'où vient le problème ...

edit

Aujourd'hui, c'est toujours le même code, mais j'obtiens une autre erreur...
A mon avis, le changement de problème doit venir des fichiers pyc, ils doivent pas se mettre à jour régulièrement.
La nouvelle erreur:
Traceback (most recent call last):
  File "K:\IUT informatique\Python\PyGTK\quizz\quizz.py", line 61, in <module>
    print test
  File "K:\IUT informatique\Python\PyGTK\quizz\quizz.py", line 56, in __str__
    retour += str(question)
  File "K:\IUT informatique\Python\PyGTK\quizz\questionSimple.py", line 20, in __str__
    return self.enonce + "\n\t" + self.reponse
TypeError: coercing to Unicode: need string or buffer, instance found


Faire print monObjetQuestion fonctionne pourtant correctement si on le fait à partir du fichier questionSimple.py

Et si je veux obtenir mon ancien soucis, il suffit que je replace str(question) par repr(question), et comme ça j'obtient l'adresse mémoire de mon objet...

Tout ce que je veux faire, c'est faire appel à la méthode __str__ de mon objet question, ça devrait pas être compliqué pourtant! :-)

Re-edit

J'ai trouvé pourquoi ça me mettait l'erreur de blabla d'unicode. ça venait du '°' dans question n° ...
Du coup, maintenant que je l'enleve, je vois bien que le fonction str de l'objet QuestionSimple n'est pas appelée!
Quizz :livres

 Question n1:
<questionSimple.QuestionSimple instance at 0x0190E198>
 Question n2:
<questionSimple.QuestionSimple instance at 0x019985D0>
 Question n3:
<questionChoixMultiple.QuestionChoixMultiple instance at 0x0190E2D8>


Quelqu'un a une idée de pourquoi?
  • Partager sur Facebook
  • Partager sur Twitter
18 février 2010 à 2:59:52

Et si tu remplaces __str__ par __repr__ pour voir ?
  • Partager sur Facebook
  • Partager sur Twitter
18 février 2010 à 14:16:37

Tout d'abord, merci d'avoir pris le temps de regarder mon problème :-)

J'ai essayé de changer les str en repr, mais ça fait toujours la même erreur.
De toute façon, ce que je veux faire c'est redéfinir la méthode str (équivalent du toString en JAVA).
C'est étonnant, j'ai l'impression que je ne peux accéder qu'à l'adresse mémoire de ces objets QuestionSimple et QuestionMultiple, sans pouvoir accéder à leurs méthodes.
Par contre, je peux accéder à leurs attributs (faire un monObjet.enonce me renvoit bien l'énoncé de la question)
A mon avis, ça doit venir de la méthode __str__ que je dois mal redéfinir, je ne vois que ça :(
Parce que quand je concatène une chaine de caractères avec str(question), il me dit qu'il ne peux pas concaténer une chaine de caractères avec une instance.
  • Partager sur Facebook
  • Partager sur Twitter
18 février 2010 à 15:13:21

Bonjour,

Je n'arrive pas à voir de problème.

J'ai reconstitué un code éxécutable pour tester (sans toucher à tes __str__()) :
question.py
class QuestionSimple:
    def __init__(self,enonce,reponse):
        self.enonce = enonce
        self.reponse = reponse

    def __str__(self):
        return self.enonce + "\n\t" + self.reponse


quizz.py
from question import QuestionSimple

class Quizz:
    def __init__(self, nom):
        self.nom = nom
        self.questions = []

    def addQuestion(self, q):
        self.questions.append(q)

    def __str__(self):
        retour = "Quizz :" + self.nom + "\n"
        for index, question in enumerate(self.questions):
            retour += "\n Question n "+ str(index+1) + ":\n"
            retour += str(question)
        return retour

if __name__ == "__main__":
    test = Quizz("livres")
    test.addQuestion(QuestionSimple("question1","reponse1"))
    test.addQuestion(QuestionSimple("question2","reponse2"))

    print test

et ca fonctionne :
$ python quizz.py
Quizz :livres

 Question n 1:
question1
        reponse1
 Question n 2:
question2
        reponse2


N'as-tu pas la possibilité de poster la totalité de ton code qu'on essaie de reproduire le problème sur nos machines ?
  • Partager sur Facebook
  • Partager sur Twitter
18 février 2010 à 15:39:35

Voici tout mon code:

Question.py
# -*- coding: cp1252 -*-

class Question:
    """ Classe générique de question. Elle est etendue par QuestionSimple et QuestionChoixMultiple"""
    def __init__(self, enonce, tempsReponse=None):
        """ Si le temps de réponse est entré, il sera pris en compte à la place du temps de réponse par défaut du quizz
            enonce : Enonce de la question
            tempsReponse : temps de réponse maximal pour répondre à la question"""
        self.enonce = enonce
        self.tempsReponse = tempsReponse



QuestionSimple.py
# -*- coding: cp1252 -*-
from xml.dom import minidom, Node
from question import Question
import os

class QuestionSimple(Question):
    "Question dont la réponse est une chaine de caractères"
    def __init__(self, enonce, reponse, tempsReponse=None):
        """ enonce:  string, Enonce de la question
            reponse: string, la réponse à la question
            tempsReponse: temps de réponse maximal pour la question"""
        Question.__init__(self, enonce, tempsReponse)
        self.reponse = reponse
        
    def reponseValide(self, reponse):
        "Renvoie True si la réponse est valide"
        return reponse == self.reponse
    
    def __str__(self):
        return self.enonce + "\n\t" + self.reponse

if __name__ == "__main__":
    test = QuestionSimple("Qui a ecrit dune?", "Frank Herbert")
    print test
    print test.reponseValide("Frank Herbert")


QuestionChoiXMultiple.py:
# -*- coding: cp1252 -*-
from question import Question

class QuestionChoixMultiple(Question):
    def __init__(self, texte, listeReponse, listeBonnesReponses, tempsReponse=None):
        Question.__init__(self, texte, tempsReponse)
        self.listeReponsesAffichees = listeReponse
        self.listeBonnesReponses = listeBonnesReponses
        
    def reponseValide(self, reponses):
        "Renvoie True si la réponse est valide"
        for reponse in reponses:
            if not(reponse in self.listeBonnesReponses):
                return False
        return True

    def __str__(self):
        retour = self.texte
        for reponse in self.listeReponsesAffichees:
            retour += "\n\t"
            if reponse in self.listeBonnesReponses:
                retour += "VRAI : "
            retour += reponse
        return retour

if __name__ == "__main__":
    test = QuestionChoixMultiple("Question test, les bonnes réponses sont la A et la C", ["A", "B", "C"], ["A", "C"])
    print test
    print test.reponseValide(["A", "C", "D"])


Quizz.py:
# -*- coding: cp1252 -*-
from xml.dom import minidom, Node
from questionSimple import QuestionSimple
from questionChoixMultiple import QuestionChoixMultiple
import os

class Quizz:
    def __init__(self, nom):
        self.nom = nom
        fichierXML = nom + ".xml"
        if not(fichierXML in os.listdir('quizz/')):
            raise NameError("Le fichier "+ fichierXML +" n'existe pas")

        # Récupération de la valeur du noeud difficultée s'il existe
        objetXML = minidom.parse('quizz/'+fichierXML)
        if len(objetXML.getElementsByTagName("difficulte")) != 0:
            self.difficulte = objetXML.getElementsByTagName("difficulte")[0].childNodes[0].nodeValue
        else:
            self.difficulte = "Non renseignée"

        # Récupération des questions du fichier XML
        self.questions = list()
        noeudsQuestion = objetXML.getElementsByTagName("question")
        for question in noeudsQuestion:
            
            enonce = question.getElementsByTagName("enonce")[0].childNodes[0].nodeValue
            reponses = question.getElementsByTagName("reponse")
            tempsReponse = question.getAttribute("tempsReponse")
            if len(tempsReponse) == 0:
                # tempsReponse vaut None s'il n'est pas renseigné
                tempsReponse = None
            # S'il n'y a qu'une réponse, c'est une question simple
            if len(reponses) == 1:
                self.questions.append(QuestionSimple(enonce, reponses[0], tempsReponse))
            # S'il y a plusieurs réponses, c'est une question à choix multiple
            elif len(reponses) > 1:
                listeReponsesAffichee = list()
                listeBonnesReponses = list()
                for reponse in reponses:
                    listeReponsesAffichee.append(reponse.childNodes[0].nodeValue)
                    if reponse.hasAttribute("valide"):
                        listeBonnesReponses.append(reponse.childNodes[0].nodeValue)
                if len(listeBonnesReponses) == 0:
                    # Une question à choix multiple a au moins une bonne réponse
                    raise NameError("La question à choix multiple \""+enonce+"\" n'a pas de réponse valide. Veuillez en définir 1 ou plusieurs comme valide dans le XML")
                
                self.questions.append(QuestionChoixMultiple(enonce, listeReponsesAffichee, listeBonnesReponses, tempsReponse))
            # On lance une erreur s'il n'y a pas de question
            else:
                raise NameError("Erreur: La quizz n'a pas de question")
            
    def __str__(self):
        retour = "Quizz :" + self.nom + "\n"
        for index, question in enumerate(self.questions):
            retour += "\n Question n"+ str(index+1) + ":\n"
            retour += str(question)
        return retour
    
if __name__ == "__main__":     
    test = Quizz("livres")
    print test


quizz/livres.xml:
<?xml version="1.0" encoding="latin1"?>
<!DOCTYPE quizz SYSTEM "quizz.dtd">
<quizz>
	<difficulte>Moyen</difficulte>
	<question id="1" tempsReponse="3">
		<enonce>Quel est l'auteur de Dune?</enonce>
		<reponse>Frank Herbert</reponse>
	</question>
	<question id="2">
		<enonce>Quel est le surnom de paul atreides?</enonce>
		<reponse>Muad dib</reponse>
	</question>
	<question id="3">
		<enonce>Parmi ces factions, lequels font partie du roman Dune?</enonce>
		<reponse valide="True">Atréides</reponse>
		<reponse valide="True">Bene Gesserit</reponse>
		<reponse>Maldaciens</reponse>
	</question>
</quizz>


Je veux que mon programme prenne les questions à partir d'un fichier XML.

Sinon, si vous avez des commentaires sur la qualité de mon code ou autre, je suis preneur. Là je code pour le plaisir et aussi pour m'améliorer, donc toutes les aides sont les bienvenues :-)
  • Partager sur Facebook
  • Partager sur Twitter
18 février 2010 à 16:07:53

C'est parti pour l'investigation :

Traceback (most recent call last):            
  File "Quizz.py", line 61, in <module>       
    print test                                
  File "Quizz.py", line 56, in __str__        
    retour += str(question)                   
  File "/home/grinwik/devel/tmp/questionSimple.py", line 22, in __str__
    return self.enonce + "\n\t" + self.reponse                         
TypeError: coercing to Unicode: need string or buffer, instance found

Est-ce donc bien une chaine qu'on recoit ?
Test :
class QuestionSimple(Question):
    "Question dont la réponse est une chaine de caractères"
    def __init__(self, enonce, reponse, tempsReponse=None):
        """ enonce:  string, Enonce de la question
            reponse: string, la réponse à la question
            tempsReponse: temps de réponse maximal pour la question"""
        Question.__init__(self, enonce, tempsReponse)
        self.reponse = reponse
        print reponse

<DOM Element: reponse at 0xb7c61acc>
<DOM Element: reponse at 0xb7c61d2c>
Traceback..

On s'attends à du type 'str' et on a un objet DOM. L'erreur est donc du coté du parseur XML.

Après quelques test ça vient d'ici :
QuestionSimple(enonce, reponses[0], tempsReponse)

Avec ça ça passe :
QuestionSimple(enonce, reponses[0].childNodes[0].nodeValue, tempsReponse)


(je n'ai jamais traité d'XML donc pas grand chose à dire sur le code).

Pour éviter ce genre d'erreur, il y a des outils à base de décorateur pour rajouter une vérification des types des arguments passés aux fonctions :
http://www.fightingquaker.com/pyanno/
  • Partager sur Facebook
  • Partager sur Twitter
18 février 2010 à 16:19:17

Merci beaucoup! Je suis habitué aux langages fortement typés comme le JAVA, du coup j'ai pas encore les bons réflexes de débogage pour le python :- )

Ca marche ! (sauf quand mon XML contient des caractères qui ne sont pas dans la table ascii, dommage!)
Quizz :livres

 Question n1:
Quel est l'auteur de Dune?
        Frank Herbert
 Question n2:
Quel est le surnom de paul atreides?
        Muad dib
 Question n3:
Parmi ces factions, lequels font partie du roman Dune?
        VRAI : Atreides
        VRAI : Bene Gesserit
        Maldaciens
  • Partager sur Facebook
  • Partager sur Twitter
22 juin 2019 à 15:41:37

bonsoir j'ai probléme  dans python3  voila l'erreur

C:\Users\randa\premier_projet\mysite> python manage.py shell

Traceback (most recent call last):

  File "manage.py", line 21, in <module>

    main()

  File "manage.py", line 17, in main

    execute_from_command_line(sys.argv)

  File "C:\Users\randa\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line

    utility.execute()

  File "C:\Users\randa\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\management\__init__.py", line 357, in execute

    django.setup()

  File "C:\Users\randa\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\__init__.py", line 24, in setup

    apps.populate(settings.INSTALLED_APPS)

  File "C:\Users\randa\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\apps\registry.py", line 114, in populate

    app_config.import_models()

  File "C:\Users\randa\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\apps\config.py", line 211, in import_models

    self.models_module = import_module(models_module_name)

  File "C:\Users\randa\AppData\Local\Programs\Python\Python37-32\lib\importlib\__init__.py", line 127, in import_module

    return _bootstrap._gcd_import(name[level:], package, level)

  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import

  File "<frozen importlib._bootstrap>", line 983, in _find_and_load

  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked

  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked

  File "<frozen importlib._bootstrap_external>", line 724, in exec_module

  File "<frozen importlib._bootstrap_external>", line 860, in get_code

  File "<frozen importlib._bootstrap_external>", line 791, in source_to_code

  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed

  File "C:\Users\randa\premier_projet\mysite\polls\models.py", line 11

    def was_published_recently(self):

                                    ^

IndentationError: unindent does not match any outer indentation level

C:\Users\randa\premier_projet\mysite>

-
Edité par randamaghraoui 22 juin 2019 à 15:43:01

  • Partager sur Facebook
  • Partager sur Twitter
22 juin 2019 à 23:42:52

Bonjour, le forum Python c'est ici https://openclassrooms.com/forum/categorie/langage-python merci de crer votre propre sujet.

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter