web-dev-qa-db-fra.com

objet à chaîne en Python

J'ai quelques objets de données sur lesquels je veux implémenter des fonctions to string et equals qui vont en profondeur. 

J'ai implémenté str et eq et bien que l'égalité fonctionne bien, je ne peux pas faire en sorte que str se comporte de la même manière:

class Bean(object):

    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2

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

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

Quand je cours:

t1 = Bean("bean 1", [Bean("bean 1.1", "same"), Bean("bean 1.2", 42)])
t2 = Bean("bean 1", [Bean("bean 1.1", "same"), Bean("bean 1.2", 42)])
t3 = Bean("bean 1", [Bean("bean 1.1", "different"), Bean("bean 1.2", 42)])

print(t1)
print(t2)
print(t3)
print(t1 == t2)
print(t1 == t3)

Je reçois:

{'attr2': [<__main__.Bean object at 0x7fc092030f28>, <__main__.Bean object at 0x7fc092030f60>], 'attr1': 'bean 1'}
{'attr2': [<__main__.Bean object at 0x7fc091faa588>, <__main__.Bean object at 0x7fc092045128>], 'attr1': 'bean 1'}
{'attr2': [<__main__.Bean object at 0x7fc0920355c0>, <__main__.Bean object at 0x7fc092035668>], 'attr1': 'bean 1'}
True
False

puisque t1 et t2 contiennent les mêmes valeurs, les égaux retournent vrai (comme prévu), tandis que puisque t3 contient une valeur différente dans la liste, le résultat est faux (aussi comme prévu) . Ce que j'aimerais, c'est avoir le même comportement pour la chaîne to (pour aller en profondeur aussi pour les éléments de la liste (ou set ou dict ...).

Pour imprimer (t1) je voudrais obtenir quelque chose comme:

{'attr2': ["{'attr2': 'same', 'attr1': 'bean 1.1'}", "{'attr2': 42, 'attr1': 'bean 1.2'}"], 'attr1': 'bean 1'}

qui est effectivement obtenu si je le fais:

Bean("bean 1", [Bean("bean 1.1", "same").__str__(), Bean("bean 1.2", 42).__str__()]).__str__

Comme je ne connais pas les types d'attributs attr1, attr2 dans mes objets Bean (qu'il s'agisse de listes mais également d'ensembles, de dictionnaires, etc.), il serait bien d'avoir une solution simple et élégante ne nécessitant pas de vérification de type ...

Est-ce possible ?

7
Valerian

Vous pouvez utiliser __repr__ au lieu de __str__, qui fonctionne de manière récursive, bien que ce ne soit pas une bonne idée la plupart du temps (regardez this answer pour plus de détails). Néanmoins, cela fonctionne pour moi:

def __repr__(self):
    return str(self.__dict__)
19
alexpeits

Vous pouvez essayer d'utiliser repr au lieu de str.

J'ai obtenu la sortie ci-dessous pour print (t1), en utilisant def repr (self): au lieu de str. 

{'attr1': 'bean 1', 'attr2': [{'attr1': 'bean 1.1', 'attr2': 'identique'}, {'attr1': 'bean 1.2', 'attr2' : 42}]}

Faites-moi savoir si cela résout votre problème. Joindre image pour référence.

Cordialement, Vinith

1
Vinith Srinivas