124 votes

Confusion au sujet de __str__ sur une liste en Python

Venant d'un milieu Java, je comprends que __str__ est quelque chose comme une version Python de toString (bien que je réalise que Python est le langage le plus ancien).

J'ai donc défini une petite classe ainsi qu'une __str__ comme suit :

class Node:

    def __init__(self, id):
        self.id = id
        self.neighbours = []
        self.distance = 0

    def __str__(self):
        return str(self.id)

Je crée ensuite quelques instances de celui-ci :

uno = Node(1)    
due = Node(2)    
tri = Node(3)    
qua = Node(4)

Le comportement attendu lorsqu'on essaie d'imprimer un de ces objets est que la valeur qui lui est associée est imprimée. Ceci se produit également.

print uno

donne

1

Mais quand je fais ce qui suit :

uno.neighbours.append([[due, 4], [tri, 5]])

et ensuite

print uno.neighbours

Je reçois

[[[<__main__.Node instance at 0x00000000023A6C48>, 4], [<__main__.Node instance at 0x00000000023A6D08>, 5]]]

Où je m'attendais

[[2, 4], [3, 5]]

Qu'est-ce que j'ai manqué ? Et quels sont les autres trucs dégoûtants que je fais ? :)

149voto

Sven Marnach Points 133943

Python dispose de deux méthodes différentes pour convertir un objet en chaîne de caractères : str() y repr() . L'impression d'un objet utilise str() ; l'impression d'une liste contenant un objet utilise str() pour la liste elle-même, mais l'implémentation de list.__str__() appelle repr() pour les articles individuels.

Vous devez donc également écraser __repr__() . Un simple

__repr__ = __str__

à la fin du corps de la classe fera l'affaire.

44voto

Hans Then Points 5570

En raison de l'infinie supériorité de Python par rapport à Java, Python n'a pas un mais deux des opérations de type "toString".

L'un est __str__ l'autre est __repr__

__str__ retournera une chaîne de caractères lisible par l'homme. __repr__ renverra une représentation interne.

__repr__ peut être invoquée sur un objet en appelant repr(obj) ou en utilisant des backticks `obj` .

Lors de l'impression de listes ainsi que d'autres classes de conteneurs, les éléments contenus seront imprimés à l'aide de la fonction __repr__ .

25voto

jax Points 1136

Il fournit une version lisible par l'homme de la sortie plutôt qu'un "objet" : Exemple :

class Pet(object):

    def __init__(self, name, species):
        self.name = name
        self.species = species

    def getName(self):
        return self.name

    def getSpecies(self):
        return self.species

    def Norm(self):
        return "%s is a %s" % (self.name, self.species)

if __name__=='__main__':
    a = Pet("jax", "human")
    print a 

renvoie à

<__main__.Pet object at 0x029E2F90>

alors que le code avec " str " renvoie quelque chose de différent

class Pet(object):

    def __init__(self, name, species):
        self.name = name
        self.species = species

    def getName(self):
        return self.name

    def getSpecies(self):
        return self.species

    def __str__(self):
        return "%s is a %s" % (self.name, self.species)

if __name__=='__main__':
    a = Pet("jax", "human")
    print a 

retours :

jax is a human

11voto

trapicki Points 363

Réponse à la question

Comme indiqué dans un autre réponse et comme vous pouvez le lire dans PEP 3140 , str sur un list appels pour chaque élément __repr__ . Il n'y a pas grand-chose que vous puissiez faire à ce sujet.

Si vous mettez en œuvre __repr__ vous obtiendrez quelque chose de plus descriptif, mais qui, s'il est mis en œuvre correctement, ne correspond pas exactement à ce que vous attendiez.

Mise en œuvre correcte

Le site rapide, mais faux La solution est d'aliaser __repr__ à __str__ .

__repr__ ne doit pas être fixé à __str__ sans condition . __repr__ devrait créer un cela devrait ressembler à une expression Python valide qui pourrait être utilisée pour recréer un objet avec la même valeur . Dans ce cas, il s'agirait plutôt Node(2) que 2 .

Une mise en œuvre correcte de __repr__ permet de recréer l'objet. Dans cet exemple, il devrait également contenir les autres membres significatifs, tels que neighours y distance .

Un site incomplet exemple :

class Node:

    def __init__(self, id, neighbours=[], distance=0):
        self.id = id
        self.neighbours = neighbours
        self.distance = distance

    def __str__(self):
        return str(self.id)

    def __repr__(self):
        return "Node(id={0.id}, neighbours={0.neighbours!r}, distance={0.distance})".format(self)
        # in an elaborate implementation, members that have the default
        # value could be left out, but this would hide some information

uno = Node(1)    
due = Node(2)    
tri = Node(3)    
qua = Node(4)

print uno
print str(uno)
print repr(uno)

uno.neighbours.append([[due, 4], [tri, 5]])

print uno
print uno.neighbours
print repr(uno)

Note : print repr(uno) ainsi qu'une mise en œuvre adéquate de __eq__ y __ne__ o __cmp__ permettrait de recréer l'objet et de vérifier l'égalité.

9voto

Eh bien, les "objets conteneurs __str__ les méthodes utiliseront repr sur leur contenu, et non str . Vous pouvez donc utiliser __repr__ au lieu de __str__ étant donné que vous utilisez un ID comme résultat.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X