Diferencia entre __str__y __repr__

python magic-methods repr


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




Answer 1 moshez


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

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__ objetivo de __repr__ es ser inequívoco
  • __str__ objetivo __str__ es ser legible
  • El contenedor __str__ utiliza objetos contenidos ' __repr__

La implementación predeterminada es inútil

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

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

habría sido demasiado peligroso (por ejemplo, demasiado fácil entrar en una recursión infinita si los objetos se refieren entre sí). Entonces Python se las arregla. Tenga en cuenta que hay un valor predeterminado que es verdadero: si __repr__ está definido y __str__ no, el objeto se comportará como si __str__=__repr__ .

Esto significa, en términos simples: casi todos los objetos que implemente deben tener un __repr__ funcional que se pueda usar para comprender el objeto. La implementación de __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

Déjame salir y decirlo: no creo en depuradores. Realmente no sé cómo usar ningún depurador, y nunca he usado uno en serio. Además, creo que la gran falla en 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 sí creo, con fervor religioso, en la tala. El registro es el elemento vital de cualquier sistema de servidor decente para 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 repr útil, por lo que un código como ese simplemente puede funcionar. Esta es la razón por la que surge la cuestión "eval": si tiene suficiente información para eval(repr(c))==c , eso significa que sabe todo lo que hay que saber sobre c . Si eso es lo suficientemente fácil, al menos de manera difusa, hazlo. De lo contrario, asegúrese de tener suficiente información sobre c de todos modos. Usualmente uso un formato de evaluación: "MyClass(this=%r,that=%r)" % (self.this,self.that) . No significa que pueda construir MyClass, o que esos sean los argumentos de constructor correctos, pero es una forma útil para expresar "esto es todo lo que necesita saber sobre esta instancia".

Nota: Utilicé %r arriba, no %s . Siempre desea usar repr() [o el carácter de formato %r , equivalente] dentro de la implementación de __repr__ , o está derrotando el objetivo de repr. Desea poder diferenciar MyClass(3) y MyClass("3") .

El objetivo de __str__ es ser legible

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

El contenedor __str__ utiliza objetos contenidos ' __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 en 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, solo

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

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

Summary

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 tenga un error de legibilidad.




Answer 2 Ned Batchelder


Mi regla general: __repr__ es para desarrolladores, __str__ es para clientes.




Answer 3 Alex Martelli


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

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

Como puede ver, no hay diferencia y no hay información más allá de la clase y la id entificación del objeto . 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 anula __repr__ , TAMBIÉN se usa para __str__ , pero no al revés.

Otros datos cruciales que debe conocer: __str__ en un contenedor incorporado utiliza __repr__ , NO __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 la __repr__ de los objetos sea una cadena que eval puede usar para construir un objeto igual (es demasiado difícil, Y no saber cómo se importó realmente el módulo relevante) en realidad es completamente imposible).

Por lo tanto, mi consejo: ¡enfóquese en hacer que __str__ sea razonablemente legible para los humanos y __repr__ lo más ambiguo posible, incluso si eso interfiere con el objetivo difuso inalcanzable de hacer que el valor devuelto de __repr__ sea ​​aceptable como entrada para __eval__ !




Answer 4 Andrew Clark


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

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

e.g.

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



Answer 5 bitoffdev


En resumen, el objetivo de __repr__ es ser inequívoco y __str__ es legible.

Aquí hay 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 la representación:

repr(object)

Devuelve una cadena que contiene una representación imprimible de un objeto. Este es el mismo valor producido por las conversiones (comillas inversas). A veces es útil poder acceder a esta operación como una función ordinaria. Para muchos tipos, esta función intenta devolver una cadena que arrojaría un objeto con el mismo valor cuando se pasa a eval() ; de lo contrario, la representación es una cadena entre corchetes angulares que contiene el nombre del tipo del objeto. con información adicional que 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__() .

Aquí está la documentación para str:

str(object='')

Devuelve una cadena que contiene una representación muy bien imprimible de un objeto. Para cadenas, esto devuelve la cadena en sí. La diferencia con repr(object) es que str(object) no siempre intenta devolver una cadena que sea aceptable para eval() ; su objetivo es devolver una cadena imprimible. Si no se proporciona ningún argumento, devuelve la cadena vacía, '' .