Hoe kan ik instanties van een klasse afdrukken met print()?

Ik leer de kneepjes van het vak in Python. Wanneer ik een object van de klasse Foobar probeer af te drukken met de functie print(), krijg ik een uitvoer zoals dit:

<__main__.Foobar instance at 0x7ff2a18c>

Is er een manier waarop ik het afdrukgedrag (of de tekenreeksrepresentatie) van een klasse en zijn objecten? Als ik bijvoorbeeld print() aanroep voor een klasseobject, wil ik de gegevensleden ervan in een bepaald formaat afdrukken. Hoe bereik je dit in Python?

Als je bekend bent met C++-klassen, kan het bovenstaande voor de standaard ostream worden bereikt door een friend ostream& operator << (ostream&, const Foobar&) methode voor de klas.


Antwoord 1, autoriteit 100%

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

De __str__ methode is wat wordt aangeroepen gebeurt wanneer u het afdrukt, en de __repr__-methode is wat er gebeurt als je de repr() gebruikt -functie (of als je ernaar kijkt met de interactieve prompt).

Als er geen __str__ methode is opgegeven, zal Python in plaats daarvan het resultaat van __repr__ afdrukken. Als u __str__ definieert maar niet __repr__, gebruikt Python wat u hierboven ziet als de __repr__, maar gebruikt u nog steeds __str__ om af te drukken.


Antwoord 2, autoriteit 20%

Zoals Chris Lutz al zei, wordt dit gedefinieerd door de __repr__ methode in je klas.

Uit de documentatie van repr() :

Voor veel typen doet deze functie een poging om een ​​string terug te geven die een object met dezelfde waarde zou opleveren als het wordt doorgegeven aan eval(), anders is de representatie een string tussen punthaken die bevat de naam van het type object samen met aanvullende informatie, vaak inclusief de naam en het adres van het object. Een klasse kan bepalen wat deze functie voor zijn instanties retourneert door een methode __repr__() te definiëren.

Gegeven de volgende klasse Test:

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)

..het werkt als volgt in de Python-shell:

>>> 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

Als er geen __str__ methode is gedefinieerd, zal print(t) (of print(str(t))) het resultaat gebruiken van __repr__ in plaats daarvan

Als er geen __repr__-methode is gedefinieerd, wordt de standaardmethode gebruikt, wat vrijwel gelijk is aan..

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

Antwoord 3, autoriteit 9%

Een generieke manier die op elke klasse kan worden toegepast zonder specifieke opmaak kan als volgt worden gedaan:

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__)

En dan,

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

produceert

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

Antwoord 4, autoriteit 6%

Als u zich in een situatie als @Keith bevindt, kunt u het volgende proberen:

print(a.__dict__)

Het druist in tegen wat ik als een goede stijl zou beschouwen, maar als je gewoon probeert te debuggen, dan zou het moeten doen wat je wilt.


Antwoord 5, autoriteit 2%

Een mooiere versie van de reactie van @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)

Produceert een visueel mooie lijst met namen en waarden.

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

Een nog mooiere versie (bedankt Ruud) sorteert de items:

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

Antwoord 6, autoriteit 2%

Om even mijn twee cent toe te voegen aan het antwoord van @dbr, volgt hier een voorbeeld van hoe deze zin te implementeren uit de officiële documentatie die hij heeft geciteerd:

“[…] om een ​​string terug te geven die een object zou opleveren met dezelfde waarde wanneer doorgegeven aan eval(), […]”

Gezien deze klassedefinitie:

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)

Het is nu eenvoudig om de instantie van de klasse Test te serialiseren:

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

Dus als we het laatste stukje code uitvoeren, krijgen we:

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")

Maar, zoals ik al zei in mijn laatste opmerking: meer info is gewoon hier!


Antwoord 7, autoriteit 2%

Je moet __repr__ gebruiken. Dit is een standaardfunctie zoals __init__.
Bijvoorbeeld:

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

Antwoord 8, autoriteit 2%

Voor Python 3:

Als het specifieke formaat niet belangrijk is (bijvoorbeeld voor debuggen), erft u het gewoon van de afdrukbare klasse hieronder. Het is niet nodig om voor elk object code te schrijven.

Geïnspireerd door dit antwoord

class Printable:
    def __repr__(self):
        from pprint import pformat
        return "<" + type(self).__name__ + "> " + 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)

Antwoord 9

Er zijn al veel antwoorden in deze thread, maar geen van hen heeft me echt geholpen, ik moest het zelf oplossen, dus ik hoop dat deze wat informatiever is.

Je moet er alleen voor zorgen dat je haakjes hebt aan het einde van je les, bijvoorbeeld:

print(class())

Hier is een voorbeeld van code van een project waar ik aan werkte:

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")

Om mijn waterstofklasse af te drukken, heb ik het volgende gebruikt:

print(Hydrogen())

Let op, dit werkt niet zonder de haakjes aan het einde van Waterstof. Ze zijn nodig.

Ik hoop dat dit helpt. Laat het me weten als je nog vragen hebt.


Antwoord 10

__repr__ en __str__ worden al in veel antwoorden genoemd. Ik wil alleen toevoegen dat als je te lui bent om deze magische functies aan je klas toe te voegen, je objprint kunt gebruiken een>. Een eenvoudige decorateur @add_objprint zal je helpen de __str__ methode toe te voegen aan je klas en je kunt print gebruiken voor de instantie. Als je wilt, kun je natuurlijk ook de functie objprint uit de bibliotheek gebruiken om willekeurige objecten in een voor mensen leesbaar formaat af te drukken.

from objprint import add_objprint
class Position:
    def __init__(self, x, y):
        self.x = x
        self.y = y
@add_objprint
class Player:
    def __init__(self):
        self.name = "Alice"
        self.age = 18
        self.items = ["axe", "armor"]
        self.coins = {"gold": 1, "silver": 33, "bronze": 57}
        self.position = Position(3, 5)
print(Player())

De uitvoer is als

<Player
  .name = 'Alice',
  .age = 18,
  .items = ['axe', 'armor'],
  .coins = {'gold': 1, 'silver': 33, 'bronze': 57},
  .position = <Position
    .x = 3,
    .y = 5
  >
>

Antwoord 11

Eenvoudig. Doe in de print:

print(foobar.__dict__)

zolang de constructor is

__init__

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes