¿Cuál es el propósito de __str__ y __repr__?

82

Realmente no entiendo dónde están __str__y dónde se __repr__usan en Python. Quiero decir, entiendo que __str__devuelve la representación de cadena de un objeto. Pero, ¿por qué necesitaría eso? ¿En qué escenario de caso de uso? Además, leí sobre el uso de__repr__

Pero lo que no entiendo es, ¿dónde los usaría?

Daniel
fuente
4
Para cualquiera que venga de Ruby, tl; dr es: __str__= to_sy __repr__= inspect.
Ajedi32

Respuestas:

86

__repr__

Llamado por la repr()función incorporada y por conversiones de cadena (comillas inversas) para calcular la representación de cadena "oficial" de un objeto. Si es posible, esto debería verse como una expresión de Python válida que podría usarse para recrear un objeto con el mismo valor (dado un entorno apropiado).

__str__

Llamado por la str()función incorporada y por la declaración de impresión para calcular la representación de cadena "informal" de un objeto.

Úselo __str__si tiene una clase y querrá una salida informativa / informal, siempre que use este objeto como parte de una cadena. Por ejemplo, puede definir __str__métodos para los modelos de Django, que luego se renderizan en la interfaz de administración de Django. En lugar de algo como <Model object>, recibirás el nombre y apellido de una persona, el nombre y la fecha de un evento, etc.


__repr__y __str__son similares, de hecho, a veces iguales (ejemplo de la BaseSetclase sets.pyde la biblioteca estándar):

def __repr__(self):
    """Return string representation of a set.

    This looks like 'Set([<list of elements>])'.
    """
    return self._repr()

# __str__ is the same as __repr__
__str__ = __repr__
miku
fuente
1
¡Gracias! ¡Esto es exactamente lo que estaba buscando!
Daniel
lo que hace `return self._repr ()`, cuando ejecuto el código y trato de entenderlo, digo que __repr __ () toma exactamente un argumento.
brillando el
Entonces, ¿puedo usar en __repr__lugar de __str__django?
Amit Tripathi
60

El único lugar donde los usa mucho es en una sesión interactiva. Si imprime un objeto __str__, se llamará a su método, mientras que si solo usa un objeto por sí mismo, __repr__se muestra:

>>> from decimal import Decimal
>>> a = Decimal(1.25)
>>> print(a)
1.25                  <---- this is from __str__
>>> a
Decimal('1.25')       <---- this is from __repr__

El __str__está destinado a ser lo más legible posible por humanos, mientras que el __repr__objetivo debe ser algo que pueda usarse para recrear el objeto, aunque a menudo no será exactamente como se creó, como en este caso.

Tampoco es inusual para ambos __str__y __repr__para devolver el mismo valor (sobre todo para los tipos predefinidos).

Scott Griffiths
fuente
Gracias por el ejemplo, me dio una mejor comprensión de dónde se usa esto de forma predeterminada
JayRizzo
17

Saltamontes, en caso de duda ve a la montaña y lee los Textos Antiguos . En ellos encontrarás que __repr __ () debería:

Si es posible, esto debería verse como una expresión de Python válida que podría usarse para recrear un objeto con el mismo valor.

Peter Rowell
fuente
6
-1 ya que esto ni siquiera intenta responder la pregunta real, que es cuáles son los casos de uso.
Scott Griffiths
4
@ Scott: Tienes razón. Pero, de nuevo, la pregunta real no mostró absolutamente ningún intento de ir a los documentos principales en primer lugar. Una cosa es hacer una pregunta que demuestre que ha intentado responderla por sí mismo, pero todavía está un poco confundido acerca de algún aspecto de ella, y otra cosa es publicar una pregunta como esta. El simple hecho de escribir su línea de asunto como una nueva pregunta muestra que 5 de los 6 principales hilos de SO sugeridos habrían respondido a su pregunta, pero no se molestó en molestarse. No le di una respuesta clara, pero me sentí muy tentado.
Peter Rowell
1
En realidad, dijo que había leído acerca de __repr__, los documentos oficiales realmente no responden a la pregunta de por qué lo usaría, y solo porque una pregunta se responde en otro lugar no es una buena razón para que no lo sea también. respondió en SO (¡la mayoría de las veces buscar en Google lo traerá de regreso aquí!) Si no cree que vale la pena responder la pregunta, entonces simplemente no podría responderla, aunque en este caso estoy de acuerdo en que ya está muy bien cubierta en SO y así vincular a duplicados sería una respuesta adecuada.
Scott Griffiths
De hecho, estás equivocado. Los documentos dicen explícitamente por qué lo usaría, a saber: "Esto se usa generalmente para depurar, por lo que es importante que la representación sea rica en información y sin ambigüedades". He visto demasiados foros (¿foros?) Hundirse bajo el peso de Help Vampires y me duele ver que comienza a pasar por SO. En cuanto a la vinculación a las otras respuestas obvias de SO, ese es todo el propósito del mecanismo de sugerencia que se activa cuando está escribiendo su línea de Asunto, sin embargo, eligió ignorar todas las sugerencias. QED y PDQ también.
Peter Rowell
5
Bueno, los documentos todavía no dicen cómo usarlo para depurar, pero realmente no tenía la intención de discutir sobre esto. Al menos estamos de acuerdo en que su respuesta no abordó la pregunta, por lo que mi -1 todavía se siente justificado para mí. Si una pregunta está mal redactada / duplicada / trivial, puede ayudar a mejorar la pregunta, vincularla a duplicados o simplemente rechazarla. Creo que mi principal objeción aquí es que las respuestas deberían intentar responder a la pregunta; existen otros mecanismos para criticar la pregunta. Me callaré ahora porque creo que ambos tenemos mejores cosas que hacer aquí.
Scott Griffiths
14

Construyendo y sobre las respuestas anteriores y mostrando algunos ejemplos más. Si se usa correctamente, la diferencia entre stry repres clara. En resumen reprdebe devolver una cadena que puede ser distribuido, copiado-pegado a reconstruir el estado exacto del objeto, mientras que stres útil para loggingy observingresultados de depuración. A continuación se muestran algunos ejemplos para ver las diferentes salidas de algunas bibliotecas conocidas.

Fecha y hora

print repr(datetime.now())    #datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)
print str(datetime.now())     #2017-12-12 18:49:27.134452

El stres bueno para imprimir en un archivo de registro, donde como reprpuede ser re-utilizados si desea ejecutarlo directamente o descargarla como comandos en un archivo.

x = datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)

Numpy

print repr(np.array([1,2,3,4,5])) #array([1, 2, 3, 4, 5])
print str(np.array([1,2,3,4,5]))  #[1 2 3 4 5]

en Numpy el repres nuevamente consumible directamente.

Ejemplo de Vector3 personalizado

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

En este ejemplo, reprdevuelve de nuevo una cadena que se puede consumir / ejecutar directamente, mientras que stres más útil como salida de depuración.

v = Vector3([1,2,3])
print str(v)     #x: 1, y: 2, z: 3
print repr(v)    #Vector3([1,2,3])

Una cosa a tener en cuenta, si strno está definida repr, strllamará automáticamente repr. Entonces, siempre es bueno al menos definirrepr

usuario1767754
fuente
5

Tengamos una clase sin __str__función.

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

emp1 = Employee('Ivan', 'Smith', 90000)

print(emp1)

Cuando imprimimos esta instancia de la clase emp1, esto es lo que obtenemos:

<__main__.Employee object at 0x7ff6fc0a0e48>

Esto no es muy útil, y ciertamente esto no es lo que queremos imprimir si lo estamos usando para mostrar (como en html)

Entonces ahora, la misma clase, pero con __str__función:

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

    def __str__(self):
        return(f"The employee {self.first} {self.last} earns {self.pay}.")
        # you can edit this and use any attributes of the class

emp2 = Employee('John', 'Williams', 90000)

print(emp2)

Ahora, en lugar de imprimir que hay un objeto, obtenemos lo que especificamos con el retorno de la __str__función:

The employee John Williams earns 90000

Zorana
fuente
3

strserá un formato informal y legible, mientras que reprofrecerá una representación oficial del objeto.

class Complex:
    # Constructor
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag

    # "official" string representation of an object
    def __repr__(self):
        return 'Rational(%s, %s)' % (self.real, self.imag)

    # "informal" string representation of an object (readable)
    def __str__(self):
        return '%s + i%s' % (self.real, self.imag)

    t = Complex(10, 20)

    print (t)     # this is usual way we print the object
    print (str(t))  # this is str representation of object 
    print (repr(t))  # this is repr representation of object   

Answers : 

Rational(10, 20) # usual representation
10 + i20      # str representation
Rational(10, 20)  # repr representation
Vishvajit Pathak
fuente
1

str y repr son ambas formas de representar. Puede usarlos cuando esté escribiendo una clase.

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __repr__(self):
    return "{}/{}".format(self.n, self.d)

por ejemplo, cuando imprimo una instancia, devuelve cosas.

print(Fraction(1, 2))

resultados en

1/2

mientras

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "{}/{}".format(self.n, self.d)
print(Fraction(1, 2))

también resulta en

1/2

Pero, ¿qué pasa si escribes ambos, cuál usa Python?

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "str"
def __repr__(self):
    return "repr"

print(Fraction(None, None))

Esto resulta en

str

Entonces, Python realmente usa el método str , no el método repr cuando ambos están escritos.

ReyWitherBrine
fuente
¿Esto funciona?
KingWitherBrine