¿Cuál es la diferencia entre __str__ y __repr__?

3118

¿Cuál es la diferencia entre __str__y __repr__en Python?

0
3045
+100

Alex resumió bien pero, sorprendentemente, fue demasiado conciso.

Primero, permítanme reiterar los puntos principales en la publicación de Alex :

  • La implementación predeterminada es inútil (es difícil pensar en una que no lo sea, pero sí)
  • __repr__ el objetivo es ser inequívoco
  • __str__ el objetivo es ser legible
  • Los __str__usos del contenedor contienen objetos '__repr__

La implementación predeterminada es inútil

Esto es principalmente una sorpresa porque los valores predeterminados de Python tienden a ser bastante útiles. Sin embargo, en este caso, tener un valor predeterminado para el __repr__que actuaría como:

return "%s(%r)" % (self.__class__, self.__dict__)

hubiera sido demasiado peligroso (por ejemplo, demasiado fácil entrar en una recursividad infinita si los objetos se referencian entre sí). Entonces Python sale de la policía. Tenga en cuenta que hay un valor predeterminado que es verdadero: si __repr__está definido y __str__no lo está, el objeto se comportará como tal __str__=__repr__.

Esto significa, en términos simples: casi todos los objetos que implementes deben tener una función __repr__que se pueda usar para comprender el objeto. La implementación __str__es opcional: hágalo si necesita una funcionalidad de "impresión bonita" (por ejemplo, utilizada por un generador de informes).

El objetivo de __repr__es ser inequívoco

Permítanme decirlo directamente: no creo en los depuradores. Realmente no sé cómo usar ningún depurador y nunca lo he usado en serio. Además, creo que la gran falla de los depuradores es su naturaleza básica: la mayoría de las fallas que depuro ocurrieron hace mucho, mucho tiempo, en una galaxia muy lejana. Esto significa que creo, con fervor religioso, en la tala. El registro es el elemento vital de cualquier sistema de servidor decente de "disparar y olvidar". Python facilita el registro: tal vez con algunos contenedores específicos del proyecto, todo lo que necesita es un

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

Pero tiene que hacer el último paso: asegúrese de que cada objeto que implemente tenga una reproducción útil, para que un código como ese simplemente funcione. Por eso surge la cuestión de la "evaluación": si tienes suficiente información eval(repr(c))==c, significa que sabes todo lo que hay que saber c. Si eso es lo suficientemente fácil, al menos de una manera difusa, hágalo. Si no es así, asegúrese de tener suficiente información al respecto de ctodos modos. Yo suelo usar una eval-como formato: "MyClass(this=%r,that=%r)" % (self.this,self.that). No significa que realmente pueda construir MyClass, o que esos sean los argumentos correctos del constructor, pero es una forma útil para expresar “esto es todo lo que necesita saber sobre esta instancia”.

Nota: utilicé %rarriba, no %s. Siempre desea usar repr()[o %rcarácter de formato, de manera equivalente] dentro de la __repr__implementación, o está frustrando el objetivo de repr. Quieres poder diferenciar MyClass(3)y MyClass("3").

El objetivo de __str__es ser legible

Específicamente, no se pretende que sea inequívoco, fíjese en eso str(3)==str("3"). Del mismo modo, si implementa una abstracción de IP, hacer que su str se vea como 192.168.1.1 está bien. Cuando se implementa una abstracción de fecha / hora, el str puede ser "2010/4/12 15:35:22", etc. El objetivo es representarlo de una manera que un usuario, no un programador, quiera leerlo. Corta los dígitos inútiles, finge ser otra clase; siempre que sea compatible con la legibilidad, es una mejora.

Los __str__usos del contenedor contienen objetos '__repr__

Esto parece sorprendente, ¿no? Es un poco, pero ¿qué tan legible sería si usara su __str__?

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

No muy. Específicamente, las cadenas de un contenedor encontrarían demasiado fácil alterar su representación de cadena. Ante la ambigüedad, recuerde, Python resiste la tentación de adivinar. Si desea el comportamiento anterior cuando imprime una lista, simplemente

print "[" + ", ".join(l) + "]"

(Probablemente también pueda averiguar qué hacer con los diccionarios.

Resumen

Implemente __repr__para cualquier clase que implemente. Esto debería ser una segunda naturaleza. Implemente __str__si cree que sería útil tener una versión de cadena que se equivoque en el lado de la legibilidad.

14
  • 248
    Definitivamente no estoy de acuerdo con su opinión de que la depuración no es el camino a seguir. Para el desarrollo, utilice un depurador (y / o registro), para el registro de uso de producción. Con un depurador tiene una vista de todo lo que salió mal cuando ocurrió el problema. Puedes ver la imagen completa. A menos que esté registrando TODO, no puede obtener eso. Además, si está registrando todo, tendrá que navegar a través de toneladas de datos para obtener lo que desea. Samuel 21 feb.15 a las 19:06
  • 28
    Gran respuesta (excepto la parte sobre no usar depuradores). Solo me gustaría agregar un enlace a esta otra sesión de preguntas y respuestas sobre str vs unicode en Python 3 que podría ser relevante para la discusión de las personas que han hecho el cambio. ThatAintWorking 23/03/15 a las 21:04
  • 17
    plus1 para depuradores son inútiles y no se escalan ni un centavo. En su lugar, aumente su rendimiento de registro. Y sí, esta fue una publicación bien escrita. Resulta que __repr__era lo que necesitaba para depurar. Gracias por tu ayuda. personal_cloud 29 de septiembre de 2017 a las 15:43
  • 10
    Dejando a un lado la locura del depurador, aprendí el% r y vale la pena votar de todos modosMickey Perlstein 13/12/18 a las 9:21
  • 15
    en depurador vs no depurador: no obtenga opiniones tan arraigadas. En algunas aplicaciones, la depuración no es realista, generalmente cuando se trata de tiempo real o cuando su código solo se ejecuta de forma remota en una plataforma con poco acceso o sin consola. En la mayoría de los otros casos, será mucho más rápido detenerse en una excepción para investigar o establecer un punto de interrupción, porque no tiene que pasar por miles de líneas de registro (lo que saturará su disco y ralentizará la aplicación). Por último, no siempre es posible iniciar sesión, por ejemplo, en dispositivos integrados, el depurador también es tu amigo. RedGlyph 2/08/19 a las 11:42
636

Mi regla general: __repr__es para desarrolladores, __str__es para clientes.

2
  • 10
    Esto es cierto porque para obj = uuid.uuid1 (), obj .__ str __ () es "2d7fc7f0-7706-11e9-94ae-0242ac110002" y obj .__ repr __ () es "UUID ('2d7fc7f0-7706-11e9-94ae-2 ') ". Los desarrolladores necesitan (valor + origen) mientras que los clientes necesitan un valor y no les importa cómo lo obtuvieron. Naren Yellavula 15 de mayo de 2019 a las 11:45
  • 7
    En este caso, cliente no necesariamente significa usuario final. Es el cliente o usuario del objeto. Entonces, si es un SDK, los desarrolladores de SDK lo usarán __str__para que los desarrolladores normales tengan un objeto legible. Por otro lado, __repr__es para los propios desarrolladores de SDK. Shiplu Mokaddim 9 de ene. De 2020 a las 13:16
449

A menos que actúe específicamente para asegurarse de lo contrario, la mayoría de las clases no tienen resultados útiles para:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

Como ve, no hay diferencia y no hay información más allá de la clase y el objeto id. Si solo anula uno de los dos ...:

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

como puede ver, si lo anula __repr__, TAMBIÉN se usa para __str__, pero no al revés.

Otros datos cruciales que debe saber: __str__en un contenedor integrado se usa el __repr__, NO el __str__, para los elementos que contiene. Y, a pesar de las palabras sobre el tema que se encuentran en los documentos típicos, casi nadie se molesta en hacer que los __repr__objetos sean una cadena que evalpueda usarse para construir un objeto igual (es demasiado difícil, Y no saber cómo se importó realmente el módulo relevante lo hace realmente completamente imposible).

Por lo tanto, mi consejo: concéntrese en hacer que sea __str__razonablemente legible por humanos y __repr__tan inequívoco como sea posible, incluso si eso interfiere con el objetivo difuso e inalcanzable de hacer que __repr__el valor devuelto sea aceptable como entrada __eval__.

6
  • 43
    En mis pruebas unitarias siempre verifico que se eval(repr(foo))evalúe como un objeto igual a foo. Tienes razón en que no va a trabajar fuera de mis casos de prueba, ya que no sé cómo se importa el módulo, pero esto por lo menos asegura que funciona en algunos contexto predecible. Creo que esta es una buena forma de evaluar si el resultado de __repr__es lo suficientemente explícito. Hacer esto en una prueba unitaria también ayuda a garantizar que __repr__siga los cambios en la clase. Steven T. Snyder 15/11/11 a las 19:58
  • 4
    Siempre trato de asegurarme de que o eval(repr(spam)) == spam(al menos en el contexto correcto) o eval(repr(spam))plantea un SyntaxError. De esa forma evitará confusiones. (Y eso es casi cierto para las incorporaciones y la mayoría de las stdlib, excepto, por ejemplo, las listas recursivas, donde a=[]; a.append(a); print(eval(repr(a)))te da [[Ellipses]]…) Por supuesto que no hago eso para usarlo eval(repr(spam)) , excepto como una verificación de cordura en las pruebas unitarias… pero yo a veces copie y pegue repr(spam)en una sesión interactiva. abarnert 20 de septiembre de 2014 a las 5:34
  • ¿Por qué no se utilizarían contenedores (listas, tuplas) __str__para cada elemento en lugar de __repr__? Me parece simplemente incorrecto, ya que implementé un legible __str__en mi objeto y cuando es parte de una lista, veo el más feo en su __repr__lugar. SuperGeo 26/01/18 a las 14:15
  • Me encontré con un error molesto relacionado con el hecho de que eval(repr(x))falla incluso para los tipos class A(str, Enum): X = 'x'integrados : activará SyntaxError eval(repr(A.X)). Es triste, pero comprensible. Por cierto, en eval(str(A.X))realidad funciona, pero por supuesto solo si class Aestá dentro del alcance, por lo que probablemente no sea muy útil. max 13/01/19 a las 13:26
  • @SuperGeo Otras respuestas cubren esto: strelemento de uso de contenedor reprporque [1, 2, 3]! = ["1", "2, 3"]. mtraceur 6 dic 2019 a las 8:15
180

__repr__: la representación del objeto python generalmente eval lo convertirá de nuevo a ese objeto

__str__: es lo que crees que es ese objeto en forma de texto

p.ej

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True
0
174

In short, the goal of __repr__ is to be unambiguous and __str__ is to be readable.

He aquí un buen ejemplo:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

Lea esta documentación para repr:

repr(object)

Return a string containing a printable representation of an object. This is the same value yielded by conversions (reverse quotes). It is sometimes useful to be able to access this operation as an ordinary function. For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval(), otherwise the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object. A class can control what this function returns for its instances by defining a __repr__() method.

Aquí está la documentación para str:

str(object='')

Return a string containing a nicely printable representation of an object. For strings, this returns the string itself. The difference with repr(object) is that str(object) does not always attempt to return a string that is acceptable to eval(); its goal is to return a printable string. If no argument is given, returns the empty string, ''.

2
  • 1
    ¿Cuál es el significado de cadena imprimible aquí? ¿Puedes explicarlo por favor? Vicrobot 19 de agosto de 2018 a las 5:44
  • basándonos en el ejemplo anterior de "bitoffdev" y @deadly podemos ver qué tan str es para el usuario final porque solo nos da una cadena legible donde as repr es para los desarrolladores porque nos da el valor y el tipo. Si está buscando respuestas para entrevistas, sería perfecto. PSK0007 13/07/20 a las 18:40
137

What is the difference between __str__ and __repr__ in Python?

__str__(leído como "dunder (doble subrayado) cadena") y __repr__(leído como "dunder-repper" (para "representación")) son métodos especiales que devuelven cadenas según el estado del objeto.

__repr__proporciona un comportamiento de respaldo si __str__falta.

Por lo tanto, primero debe escribir un __repr__que le permita reinstalar un objeto equivalente de la cadena que devuelve, por ejemplo, usándolo evalo escribiéndolo carácter por carácter en un shell de Python.

En cualquier momento posterior, se puede escribir un __str__para una representación de cadena legible por el usuario de la instancia, cuando se crea que es necesario.

__str__

Si imprime un objeto, o se lo pasa a format, str.formato str, si __str__se define un método, se llamará a ese método; de lo contrario, __repr__se utilizará.

__repr__

El __repr__método es llamado por la función incorporada repry es lo que se repite en su shell de Python cuando evalúa una expresión que devuelve un objeto.

Dado que proporciona una copia de seguridad para __str__, si solo puede escribir una, comience con__repr__

Aquí está la ayuda incorporada sobre repr:

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

Es decir, para la mayoría de los objetos, si escribe lo que está impreso repr, debería poder crear un objeto equivalente. Pero esta no es la implementación predeterminada.

Implementación predeterminada de __repr__

El objeto predeterminado __repr__es ( fuente C Python ) algo como:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

Eso significa que, de forma predeterminada, imprimirá el módulo del que proviene el objeto, el nombre de la clase y la representación hexadecimal de su ubicación en la memoria, por ejemplo:

<__main__.Foo object at 0x7f80665abdd0>

Esta información no es muy útil, pero no hay forma de derivar cómo se podría crear con precisión una representación canónica de una instancia determinada, y es mejor que nada, al menos decirnos cómo podríamos identificarla de forma única en la memoria.

¿Cómo puede __repr__ser útil?

Veamos qué tan útil puede ser, usando el shell y los datetimeobjetos de Python . Primero necesitamos importar el datetimemódulo:

import datetime

Si llamamos datetime.nowal shell, veremos todo lo que necesitamos para recrear un objeto de fecha y hora equivalente. Esto es creado por la fecha y hora __repr__:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

Si imprimimos un objeto de fecha y hora, vemos un buen formato legible por humanos (de hecho, ISO). Esto es implementado por datetime's __str__:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

Es muy sencillo recrear el objeto que perdimos porque no lo asignamos a una variable copiando y pegando de la __repr__salida, y luego imprimiéndolo, y lo obtenemos en la misma salida legible por humanos que el otro objeto:

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

¿Cómo los implemento?

A medida que desarrolle, querrá poder reproducir objetos en el mismo estado, si es posible. Así, por ejemplo, es como se define el objeto datetime __repr__( fuente Python ). Es bastante complejo, debido a todos los atributos necesarios para reproducir tal objeto:

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

Si desea que su objeto tenga una representación más legible por humanos, puede implementar a __str__continuación. Así es como se implementa el objeto de fecha y hora ( fuente de Python ) __str__, lo que hace fácilmente porque ya tiene una función para mostrarlo en formato ISO:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

__repr__ = __str__¿ Establecer ?

Esta es una crítica de otra respuesta aquí que sugiere un entorno __repr__ = __str__.

La configuración __repr__ = __str__es una tontería: __repr__es una alternativa __str__y __repr__, escrito para el uso de los desarrolladores en la depuración, debe escribirse antes de escribir un __str__.

Necesita un __str__solo cuando necesita una representación textual del objeto.

Conclusión

Defina los __repr__objetos que escribe para que usted y otros desarrolladores tengan un ejemplo reproducible al usarlo a medida que desarrolla. Defina __str__cuándo necesita una representación de cadena legible por humanos.

2
  • ¿No debería ser algo parecido a type(obj).__qualname__? Solomon Ucko 1 de diciembre de 2018 a las 1:10
  • @SolomonUcko sí en Python 3, ese parece ser el caso: he estado buscando el código fuente donde se implementa esto y actualizaré mi respuesta con esa información cuando la obtenga. Aaron Hall 1/12/18 a las 20:50
44

En la página 358 del libro Python scripting for computational science de Hans Petter Langtangen, se establece claramente que

  • El __repr__objetivo es una representación de cadena completa del objeto;
  • El __str__es devolver una buena cadena para imprimir.

Entonces, prefiero entenderlos como

  • repr = reproducir
  • str = string (representación)

desde el punto de vista del usuario, aunque este es un malentendido que hice al aprender Python.

También se da un ejemplo pequeño pero bueno en la misma página de la siguiente manera:

Ejemplo

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'
2
  • Está en la pág. # 351. jiten 21/12/18 a las 13:10
  • 7
    Es un poco engañoso referirse a reprreproducir. Es mejor pensar en ello como una representación. NelsonGon 19/06/19 a las 7:48
43

Aparte de todas las respuestas dadas, me gustaría agregar algunos puntos: -

1) __repr__()se invoca cuando simplemente escribe el nombre del objeto en la consola interactiva de Python y presiona enter.

2) __str__()se invoca cuando utiliza un objeto con una declaración de impresión.

3) En caso de que __str__falte, imprima y cualquier función que utilice str()invocaciones __repr__()de objeto.

4) __str__()de contenedores, cuando se invoca ejecutará el __repr__()método de sus elementos contenidos.

5) str()llamado dentro __str__()podría potencialmente recurrir sin un caso base y error en la profundidad de recursión máxima.

6) __repr__()can call repr()que intentará evitar la recursividad infinita automáticamente, reemplazando un objeto ya representado con ....

15

Para hacerlo mas simple:

__str__se utiliza para mostrar una representación de cadena de su objeto para que otros puedan leerla fácilmente .

__repr__se utiliza para mostrar una representación de cadena del objeto.

Digamos que quiero crear una Fractionclase donde la representación de cadena de una fracción sea '(1/2)' y el objeto (clase Fraction) se represente como 'Fraction (1,2)'

Entonces podemos crear una clase Fraction simple:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)
13

Con toda honestidad, eval(repr(obj))nunca se usa. Si se encuentra usándolo, debe detenerse, porque evales peligroso, y las cadenas son una forma muy ineficiente de serializar sus objetos (use pickleen su lugar).

Por lo tanto, recomendaría configurar __repr__ = __str__. La razón es que str(list)llama repra los elementos (considero que este es uno de los mayores defectos de diseño de Python que no fue abordado por Python 3). Es reprprobable que un valor real no sea muy útil como resultado de print [your, objects].

Para calificar esto, en mi experiencia, el caso de uso más útil de la reprfunción es poner una cadena dentro de otra cadena (usando formato de cadena). De esta manera, no tiene que preocuparse por escapar de las comillas ni nada. Pero tenga en cuenta que aquí no está evalsucediendo.

2
  • 19
    Creo que esto pierde el sentido. El uso de eval(repr(obj))es una prueba de cordura y una regla general: si esto recrea el objeto original correctamente, entonces tiene una __repr__implementación decente . No se pretende que realmente serialice objetos de esta manera. jwg 6/06/2014 a las 13:56
  • 8
    evalno es intrínsecamente peligroso. No es más peligrosa que unlink, openo escribir en archivos. ¿Deberíamos dejar de escribir en archivos porque quizás un ataque malintencionado podría usar una ruta de archivo arbitraria para colocar contenido dentro? Todo es peligroso si la gente tonta lo usa tontamente. La idiotez es peligrosa. Los efectos de Dunning-Kruger son peligrosos. evales solo una función. Luis Masuelli 1 de marzo de 2016 a las 15:12
12

De una Wiki de referencia de Python (no oficial) (copia de archivo) por effbot:

__str__" calcula la representación de cadena" informal "de un objeto. Esto se diferencia de __repr__que no tiene que ser una expresión válida de Python: en su lugar, se puede usar una representación más conveniente o concisa " .

1
  • 4
    __repr__de ninguna manera es necesario para devolver una expresión de Python válida. Mad Physicist 20 oct 2017 a las 3:23
11

str : Crea un nuevo objeto de cadena a partir del objeto dado.

repr - Devuelve la representación de cadena canónica del objeto.

Las diferencias:

str ():

  • hace que el objeto sea legible
  • genera resultados para el usuario final

repr ():

  • necesita un código que reproduzca el objeto
  • genera salida para el desarrollador
10

P: ¿Cuál es la diferencia entre __str__()y __repr__()?

TL; DR: Diferencias entre str () / repr () y __str __ () / __ repr __ ()

LARGO

Esta pregunta ha existido por mucho tiempo, y hay una variedad de respuestas de las cuales la mayoría son correctas (sin mencionar las de varias leyendas de la comunidad de Python [!]). Sin embargo, cuando se llega al meollo de la cuestión, la cuestión es análoga a pedir la diferencia entre el str()y repr()funciones integradas. Voy a describir las diferencias con mis propias palabras (lo que significa que puedo estar "tomando prestado" generosamente de la Programación Core Python, así que por favor perdóname).

Tanto str() y repr()tener el mismo trabajo básico: su objetivo es devolver una representación de cadena de un objeto Python. Qué tipo de representación de cadenas es lo que los diferencia.

  • str()& __str__()devolver una representación de cadena imprimible de un objeto ... algo legible por humanos / para consumo humano
  • repr()& __repr__()devuelve una representación de cadena de un objeto que es un objeto Python válido , algo que puede pasar eval()o escribir en el shell de Python sin obtener un error.

Por ejemplo, asignemos una cadena ay xuna intpara y, y simplemente mostrando versiones de cadena legibles por humanos de cada uno:

>>> x, y = 'foo', 123
>>> str(x), str(y)
('foo', '123')

¿Podemos tomar lo que está dentro de las comillas en ambos casos e ingresarlas textualmente en el intérprete de Python? Hagamos un intento:

>>> 123
123
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

Claramente se puede por un intpero no necesariamente por un str. Si bien puedo pasar '123'a eval(), eso no funciona para 'foo':

>>> eval('123')
123
>>> eval('foo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'foo' is not defined

Ahora intentemos repr(); de nuevo, descargue lo que hay en el par de comillas para cada cadena:

>>> repr(x), repr(y)
("'foo'", '123')
>>> 123
123
>>> 'foo'
'foo'

Vaya, ¿ ambos funcionan? Eso es porque 'foo', mientras que una representación de cadena imprimible de esa cadena, que es no evaluable, pero "'foo'"es. 123es un Python válido intllamado por str()o repr(). ¿Qué pasa cuando llamamos eval()con estos?

>>> eval('123')
123
>>> eval("'foo'")
'foo'

Funciona porque 123y 'foo'son objetos Python válidos. Otra conclusión clave es que, si bien a veces ambos devuelven lo mismo (la misma representación de cadena), no siempre es así. (Y sí, sí, puedo crear una variable foodonde eval()funcione, pero ese no es el punto).

Más datos sobre ambos pares

  1. A veces, str()y repr()se llaman implícitamente , lo que significa que se llaman en nombre de los usuarios: cuando los usuarios ejecutan print(Py1 / Py2) o llaman print()(Py3 +), incluso si los usuarios no llaman str()explícitamente, dicha llamada se realiza en su nombre antes del se muestra el objeto.
  2. En el shell de Python (intérprete interactivo), si ingresa una variable en el >>>indicador y presiona RETORNO, el intérprete muestra los resultados de la repr()llamada implícita en ese objeto.
  3. Para conectarse str()y repr()hacia __str__()y __repr__(), darse cuenta de que las llamadas a las funciones integradas, es decir, str(x)o repr(y)resultan en llamar a los métodos especiales correspondientes de su objeto: x.__str__()oy.__repr()__
  4. Al implementar __str__()y __repr__()para sus clases de Python, sobrecarga las funciones integradas ( str()y repr()), lo que permite que las instancias de sus clases se pasen a str()y repr(). Cuando se hacen tales llamadas, se dan la vuelta y llaman a la clase ' __str__()y __repr__()(según el n. ° 3).
0
8

Un aspecto que falta en otras respuestas. Es cierto que en general el patrón es:

  • Objetivo de __str__: legible por humanos
  • Objetivo de __repr__: inequívoco, posiblemente legible por máquina a través deeval

Desafortunadamente, esta diferenciación es defectuosa, porque Python REPL y también IPython se usan __repr__para imprimir objetos en una consola REPL (vea las preguntas relacionadas para Python e IPython ). Por lo tanto, los proyectos que están destinados al trabajo de consola interactiva (por ejemplo, Numpy o Pandas) han comenzado a ignorar las reglas anteriores y, en su lugar, proporcionan una __repr__implementación legible por humanos .

0
7

Del libro Fluent Python :

A basic requirement for a Python object is to provide usable string representations of itself, one used for debugging and logging, another for presentation to end users. That is why the
special methods __repr__ and __str__ exist in the data model.

5

Las respuestas excelentes ya cubren la diferencia entre __str__y __repr__, que para mí se reduce a que el primero es legible incluso por un usuario final, y el segundo es lo más útil posible para los desarrolladores. Dado eso, encuentro que la implementación predeterminada de a __repr__menudo no logra este objetivo porque omite información útil para los desarrolladores.

Por esta razón, si tengo una solución lo suficientemente simple __str__, generalmente trato de obtener lo mejor de ambos mundos con algo como:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))
4

One important thing to keep in mind is that container's __str__ uses contained objects' __repr__.

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python favorece la no ambigüedad sobre la legibilidad , la __str__llamada de a tuplellama a los objetos contenidos ' __repr__, la representación "formal" de un objeto. Aunque la representación formal es más difícil de leer que una informal, es inequívoca y más robusta contra los errores.

1
  • ¡Se usa __repr__ cuando ( __str__) no está definido! Entonces, estás equivocado. jiten 21/12/18 a las 13:48
4

En una palabra:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'
4
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

Cuando print()se llama, decimal.Decimal(23) / decimal.Decimal("1.05")se imprime el resultado del número sin procesar; esta salida está en forma de cadena que se puede lograr con __str__(). Si simplemente ingresamos la expresión obtenemos una decimal.Decimalsalida; esta salida está en forma representativa que se puede lograr con __repr__(). Todos los objetos de Python tienen dos formas de salida. La forma de cadena está diseñada para ser legible por humanos. La forma de representación está diseñada para producir una salida que, si se envía a un intérprete de Python, reproduciría (cuando sea posible) el objeto representado.

4

__str__se puede invocar en un objeto llamando str(obj)y debe devolver una cadena legible por humanos.

__repr__se puede invocar en un objeto llamando repr(obj)y debe devolver el objeto interno (campos / atributos del objeto)

Este ejemplo puede ayudar:

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr
3

Comprenderlos __str__y __repr__distinguirlos intuitiva y permanentemente en absoluto.

__str__devolver el cuerpo disfrazado de cadena de un objeto dado para que los ojos lo
__repr__puedan leer .

Míralo en un ejemplo

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

En cuanto a __repr__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

Podemos hacer operaciones aritméticas sobre los __repr__resultados de manera conveniente.

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

si aplica la operación en __str__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Devuelve nada más que error.

Otro ejemplo.

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

Espero que esto te ayude a construir terrenos concretos para explorar más respuestas.

3
  1. __str__debe devolver un objeto de cadena mientras que __repr__puede devolver cualquier expresión de Python.
  2. Si __str__falta la implementación, la __repr__función se utiliza como alternativa. No hay respaldo si __repr__falta la implementación de la función.
  3. Si la __repr__función devuelve una representación de cadena del objeto, podemos omitir la implementación de la __str__función.

Fuente: https://www.journaldev.com/22460/python-str-repr-functions

2

__repr__se usa en todas partes, excepto por los métodos printy str(¡cuando __str__se define a!)

1

Cada objeto hereda __repr__ de la clase base que crearon todos los objetos.

class Person:
     pass

p=Person()

si llama repr(p), obtendrá esto por defecto:

 <__main__.Person object at 0x7fb2604f03a0>

Pero si llama str(p), obtendrá el mismo resultado. es porque cuando __str__no existe, Python llama__repr__

Implementemos el nuestro __str__

class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __repr__(self):
        print("__repr__ called")
        return f"Person(name='{self.name}',age={self.age})"

p=Person("ali",20)

print(p)y str(p)volveremos

 __repr__ called
     Person(name='ali',age=20)

agreguemos __str__()

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __repr__(self):
        print('__repr__ called')
        return f"Person(name='{self.name}, age=self.age')"
    
    def __str__(self):
        print('__str__ called')
        return self.name

p=Person("ali",20)

si llamamos print(p)y str (p), llamará __str__()y devolverá

__str__ called
ali

repr(p) volverá

repr llamado "Persona (nombre = 'ali, edad = self.age')"

Omitamos __repr__y simplemente implementemos __str__.

class Person:
def __init__(self, name, age):
    self.name = name
    self.age = age

def __str__(self):
    print('__str__ called')
    return self.name

p=Person('ali',20)

print(p)buscará el __str__y volverá:

__str__ called
ali

NOTA = si lo tuviéramos __repr__y __str__definido, f'name is {p}'llamaríamos__str__

1
1

Puede obtener información de este código:

class Foo():
    def __repr__(self):
        return("repr")
    def __str__(self):
        return("str")

foo = Foo()
foo #repr
print(foo) #str