web-dev-qa-db-fra.com

Comment imprimer les instances d'une classe en utilisant print ()?

J'apprends les ficelles du métier en Python. Lorsque j'essaie d'imprimer un objet de classe Foobar à l'aide de la fonction print(), j'obtiens un résultat comme celui-ci:

<__main__.Foobar instance at 0x7ff2a18c>

Est-il possible de définir le comportement d'impression (ou la représentation de chaîne ) d'une classe et de ses objets ? Par exemple, lorsque j'appelle print() sur un objet de classe, j'aimerais imprimer ses données membres dans un certain format. Comment y parvenir en Python?

Si vous connaissez bien les classes C++, vous pouvez obtenir ce qui précède pour la variable standard ostream en ajoutant une méthode friend ostream& operator << (ostream&, const Foobar&) à la classe.

459
Ashwin Nanjappa
>>> class Test:
...     def __repr__(self):
...         return "Test()"
...     def __str__(self):
...         return "member of Test"
... 
>>> t = Test()
>>> t
Test()
>>> print(t)
member of Test

La méthode __str__ correspond à ce qui se passe lorsque vous l’imprimez, et la méthode __repr__ à l’utilisation de la fonction repr() (ou lorsque vous la regardez avec l’invite interactive ). Si ce n'est pas la méthode la plus courante Pythonic , je m'excuse, car j'apprends encore aussi - mais cela fonctionne.

Si aucune méthode __str__ n'est donnée, Python imprimera le résultat de __repr__ à la place. Si vous définissez __str__ mais pas __repr__, Python utilisera ce que vous voyez ci-dessus comme le __repr__, mais utilisera toujours __str__ pour l'impression.

539
Chris Lutz

Comme Chris Lutz l'a mentionné , ceci est défini par la méthode __repr__ de votre classe.

De la documentation de repr() :

Pour de nombreux types, cette fonction tente de renvoyer une chaîne qui donnerait un objet avec la même valeur si elle est transmise à eval(). Sinon, la représentation est une chaîne entourée de crochets angulaires contenant le nom du type de l'objet avec des informations supplémentaires. informations comprenant souvent le nom et l'adresse de l'objet. Une classe peut contrôler ce que cette fonction retourne pour ses instances en définissant une méthode __repr__().

Étant donné le test de classe suivant:

class Test:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return "<Test a:%s b:%s>" % (self.a, self.b)

    def __str__(self):
        return "From str method of Test: a is %s, b is %s" % (self.a, self.b)

..il agira de la manière suivante dans le shell Python:

>>> t = Test(123, 456)
>>> t
<Test a:123 b:456>
>>> print repr(t)
<Test a:123 b:456>
>>> print(t)
From str method of Test: a is 123, b is 456
>>> print(str(t))
From str method of Test: a is 123, b is 456

Si aucune méthode __str__ n'est définie, print(t) (ou print(str(t))) utilisera le résultat de __repr__ à la place.

Si aucune méthode __repr__ n'est définie, alors la méthode par défaut est utilisée, ce qui équivaut à peu près à ..

def __repr__(self):
    return "<%s instance at %s>" % (self.__class__.__name__, id(self))
120
dbr

Une manière générique qui peut être appliquée à n'importe quelle classe sans formatage spécifique pourrait être faite comme suit:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return str(self.__class__) + ": " + str(self.__dict__)

Puis,

elem = Element('my_name', 'some_symbol', 3)
print(elem)

produit

__main__.Element: {'symbol': 'some_symbol', 'name': 'my_name', 'number': 3}
43
user394430

Si vous êtes dans une situation comme @ Keith , vous pouvez essayer:

print a.__dict__

Cela va à l’encontre de ce que j’appellerais un bon style, mais si vous essayez simplement de déboguer, il devrait faire ce que vous voulez.

13
John

Pour ajouter mes deux cents à la réponse de @ dbr, voici un exemple d'application de cette phrase à partir de la documentation officielle qu'il a citée:

"[...] pour renvoyer une chaîne qui donnerait un objet avec la même valeur si elle est passée à eval (), [...]"

Étant donné cette définition de classe:

class Test(object):
    def __init__(self, a, b):
        self._a = a
        self._b = b

    def __str__(self):
        return "An instance of class Test with state: a=%s b=%s" % (self._a, self._b)

    def __repr__(self):
        return 'Test("%s","%s")' % (self._a, self._b)

Maintenant, il est facile de sérialiser une instance de Test class:

x = Test('hello', 'world')
print 'Human readable: ', str(x)
print 'Object representation: ', repr(x)
print

y = eval(repr(x))
print 'Human readable: ', str(y)
print 'Object representation: ', repr(y)
print

Donc, en exécutant le dernier morceau de code, nous aurons:

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Mais, comme je l’ai dit dans mon dernier commentaire: plus d’informations, c’est juste ici !

Vous devez utiliser __repr__. C'est une fonction standard comme __init__. Par exemple:

class Foobar():
    """This will create Foobar type object."""

    def __init__(self):
        print "Foobar object is created."

    def __repr__(self):
        return "Type what do you want to see here."

a = Foobar()

print a
12
flow_chart

Pour Python 3:

Si le format spécifique n’est pas important (par exemple, pour le débogage), héritez simplement de la classe Printable ci-dessous. Pas besoin d'écrire du code pour chaque objet.

Inspiré par this answer

class Printable:
    def __repr__(self):
        from pprint import pformat
        return "<" + type(self).__+ "> " + pformat(vars(self), indent=4, width=1)

# Example Usage
class MyClass(Printable):
    pass

my_obj = MyClass()
my_obj.msg = "Hello"
my_obj.number = "46"
print(my_obj)
8
PeterM

Une version plus jolie de la réponse de @ user394430

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return  str(self.__class__) + '\n'+ '\n'.join(('{} = {}'.format(item, self.__dict__[item]) for item in self.__dict__))

elem = Element('my_name', 'some_symbol', 3)
print(elem)

Produit visuellement une belle liste de noms et de valeurs.

<class '__main__.Element'>
name = my_name
symbol = some_symbol
number = 3

Une version encore plus sophistiquée (merci Ruud) trie les éléments:

def __str__(self):
    return  str(self.__class__) + '\n' + '\n'.join((str(item) + ' = ' + str(self.__dict__[item]) for item in sorted(self.__dict__)))
7
MikeyB

Il y a déjà beaucoup de réponses dans ce fil de discussion, mais aucune d’entre elles ne m’a particulièrement aidée; j’ai dû résoudre le problème moi-même. J’espère donc que celui-ci est un peu plus informatif.

Vous devez juste vous assurer que vous avez des parenthèses à la fin de votre cours, par exemple:

print(class())

Voici un exemple de code d'un projet sur lequel je travaillais:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number
    def __str__(self):
        return "{}: {}\nAtomic Number: {}\n".format(self.name, self.symbol, self.number

class Hydrogen(Element):
    def __init__(self):
        super().__init__(name = "Hydrogen", symbol = "H", number = "1")

Pour imprimer ma classe d'hydrogène, j'ai utilisé ce qui suit:

print(Hydrogen())

Veuillez noter que cela ne fonctionnera pas sans les parenthèses à la fin de l'hydrogène. Ils sont nécessaires.

J'espère que cela aide, faites-moi savoir si vous avez d'autres questions.

1
Stumpy

utilisez simplement "__ str __" méthode spéciale dans votre classe. Par ex.

classe Adiprogrammer:

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

def __str__(self):
    return "I am the Founder of Adiprogrammer!"

yash = Adiprogrammer ("Aaditya")

imprimer (yash)

1
Yash Tile