¿Cómo imprimir instancias de una clase usando print ()?

539

Estoy aprendiendo las cuerdas en Python. Cuando intento imprimir un objeto de clase Foobarusando la print()función, obtengo un resultado como este:

<__main__.Foobar instance at 0x7ff2a18c>

¿Hay alguna manera de establecer el comportamiento de impresión (o la representación de cadena ) de una clase y sus objetos ? Por ejemplo, cuando llamo print()a un objeto de clase, me gustaría imprimir sus miembros de datos en un formato determinado. ¿Cómo lograr esto en Python?

Si está familiarizado con las clases de C ++, lo anterior se puede lograr para el estándar ostreamagregando un friend ostream& operator << (ostream&, const Foobar&)método para la clase.

Ashwin Nanjappa
fuente

Respuestas:

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

El __str__método es lo que sucede cuando lo imprime, y el __repr__método es lo que sucede cuando usa la repr()función (o cuando la mira con el mensaje interactivo). Si este no es el método más pitónico , me disculpo, porque todavía estoy aprendiendo también, pero funciona.

Si no __str__se proporciona ningún método, Python imprimirá el resultado de en su __repr__lugar. Si define __str__pero no __repr__, Python usará lo que ve arriba como __repr__, pero aún lo usa __str__para imprimir.

Chris Lutz
fuente
11
también hay un método unicode , que puede usar en lugar de Str ; Tenga en cuenta que debe devolver un objeto Unicode, no es una cadena (pero si devuelve una cadena, la conversión a Unicode se llevará a cabo de todos modos ...)
kender
@kender: no lo sabía, pero en retrospectiva tiene mucho sentido dado el manejo Unicode roto de Python 2.x.
Chris Lutz
11
¡Creo que esta respuesta no se puede completar sin un enlace a esta otra !
tnotstar
¡Me salvó! Sin embargo, después de volver a implementar el método __repr __ (self), print engañará a los usuarios. ¿Conoces las mejores prácticas en torno a esto?
Viet
10
Para los programadores de Java: __str __ (self) es como el toString () del mundo python
Janac Meena
134

Como mencionó Chris Lutz , esto se define por el __repr__método en su clase.

De la documentación de repr():

Para muchos tipos, esta función intenta devolver una cadena que arrojaría un objeto con el mismo valor cuando se pasa eval(), de lo contrario, la representación es una cadena entre corchetes angulares que contiene el nombre del tipo de objeto junto con información adicional a menudo incluye el nombre y la dirección del objeto. Una clase puede controlar lo que devuelve esta función para sus instancias definiendo un __repr__()método.

Dada la siguiente clase de prueba:

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)

.. actuará de la siguiente manera en el shell de 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 no __str__se define método, print(t)(o print(str(t))) utilizará el resultado de __repr__vez

Si no __repr__se define ningún método, se utiliza el predeterminado, que es más o menos equivalente a ...

def __repr__(self):
    return "<%s instance at %s>" % (self.__class__.__name__, id(self))
dbr
fuente
+1 pero el código de tu clase __str__es diferente de los resultados del shell interactivo que das. : P
Chris Lutz
1
Err, oops ... modificar manualmente la salida REPL nunca termina bien. Probablemente debería probar mis publicaciones: P
dbr
1
El %formato de cadena no está en desuso, de docs.python.org/whatsnew/2.6.html "el operador% se complementa con un método de formato de cadena más potente, format ()"
dbr
44
Dbr: Eso es verdad. Tenga en cuenta que el documento "What's New In Python 3.0" también dice "método format () [...] El plan es hacer que esta sea la única API para el formateo de cadenas y comenzar a despreciar el operador% en Python 3.1".
Ashwin Nanjappa
1
Pitty, %ha sido muy conveniente.
Janusz Lenar
52

Una forma genérica que se puede aplicar a cualquier clase sin formato específico podría hacerse de la siguiente manera:

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

Y entonces,

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

produce

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

Si estás en una situación como @Keith, puedes probar:

print a.__dict__

Va en contra de lo que yo consideraría un buen estilo, pero si solo está tratando de depurar, entonces debería hacer lo que quiera.

Juan
fuente
¿Sabría saber si la clave dict tiene objetos en sus valores?
pranaygoyal02
1
@HadoopEvangelist ¿Estás preguntando cómo imprimir también esos objetos de forma recursiva o simplemente determinar si hay objetos?
John
13

Solo para agregar mis dos centavos a la respuesta de @ dbr, el siguiente es un ejemplo de cómo implementar esta oración de la documentación oficial que ha citado:

"[...] para devolver una cadena que arrojaría un objeto con el mismo valor cuando se pasa a eval (), [...]"

Dada esta definición de clase:

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)

Ahora, es fácil serializar la instancia de Testclase:

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

Entonces, ejecutando el último fragmento de código, obtendremos:

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

Pero, como dije en mi último comentario: ¡más información está aquí !

tnotstar
fuente
12

Necesitas usar __repr__. Esta es una función estándar como __init__. Por ejemplo:

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
diagrama de flujo
fuente
2
repr y str tienen una semántica diferente: repr debe ser una fuente de Python que (re) cree el mismo objeto; esta es su representación en código; str debería ser una bonita cadena de usuario del objeto.
Eric Towers
12

Una versión más bonita de la respuesta 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)

Produce una buena lista visual de los nombres y valores.

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

Una versión aún más elegante (gracias Ruud) clasifica los elementos:

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

Para Python 3:

Si el formato específico no es importante (por ejemplo, para la depuración) simplemente herede de la clase Printable a continuación. No es necesario escribir código para cada objeto.

Inspirado por esta respuesta

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)
PeterM
fuente
1

Ya hay muchas respuestas en este hilo, pero ninguna de ellas me ayudó particularmente, tuve que resolverlo yo mismo, así que espero que esta sea un poco más informativa.

Solo tiene que asegurarse de tener paréntesis al final de su clase, por ejemplo:

print(class())

Aquí hay un ejemplo de código de un proyecto en el que estaba trabajando:

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

Para imprimir mi clase de hidrógeno, utilicé lo siguiente:

print(Hydrogen())

Tenga en cuenta que esto no funcionará sin los paréntesis al final de Hidrógeno. Son necesarios.

Espero que esto ayude, avíseme si tiene más preguntas.

Achaparrado
fuente