metodo - repr python




Diferencia entre__str__ y__repr__? (14)

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

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

__repr__ proporciona un comportamiento de copia de seguridad si __str__ falta.

Por lo tanto, primero debe escribir un __repr__ que le permita reinstituir un objeto equivalente de la cadena que devuelve, por ejemplo, utilizando eval o escribiéndolo en carácter por carácter en un shell de Python.

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

__str__

Si imprime un objeto, o lo pasa a format , str.format o str , entonces si se define un método __str__ , se llamará a ese método; de lo contrario, se __repr__ .

__repr__

El método __repr__ es llamado por la función incorporada repr y es lo que se refleja 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 en 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 se imprime con repr , debería poder crear un objeto equivalente. Pero esta no es la implementación por defecto.

Implementación predeterminada de __repr__

El objeto predeterminado __repr__ es ( fuente de C Python ) algo así como:

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

Esto 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 manera de determinar cómo se puede crear con precisión una representación canónica de una instancia determinada, y es mejor que nada, al menos nos dice cómo podemos identificarla de forma única en la memoria.

¿Cómo puede __repr__ ser útil?

Veamos lo útil que puede ser, utilizando el shell de Python y los objetos de datetime y datetime . Primero necesitamos importar el módulo datetime :

import datetime

Si llamamos a datetime.now en el shell, veremos todo lo que necesitamos para recrear un objeto de fecha y hora equivalente. Esto es creado por el datetime __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 __str__ de datetime:

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

Es una cuestión simple recrear el objeto que perdimos porque no lo asignamos a una variable copiando y pegando desde la salida de __repr__ , y luego imprimiéndolo, y obtenemos el mismo resultado legible para el ser humano 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 se desarrolle, querrá poder reproducir objetos en el mismo estado, si es posible. Esto, por ejemplo, es cómo el objeto datetime define __repr__ ( fuente de Python ). Es bastante complejo, debido a todos los atributos necesarios para reproducir dicho 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 = ", ".join(map(str, L))
    s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    return s

Si desea que su objeto tenga una representación legible más humana, puede implementar __str__ continuación. Así es como el objeto datetime ( fuente de Python ) implementa __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=' ')

Establecer __repr__ = __str__ ?

Esta es una crítica de otra respuesta que sugiere establecer __repr__ = __str__ .

Establecer __repr__ = __str__ es una tontería - __repr__ es una alternativa para __str__ y __repr__ , escrito para 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 __repr__ para los objetos que escribe para que usted y otros desarrolladores tengan un ejemplo reproducible cuando lo usen a medida que lo desarrolla. Defina __str__ cuando necesite una representación humana de la misma.

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


En resumen, el objetivo de __repr__ es no ser ambiguo y __str__ debe ser 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 repr:

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 produciría un objeto con el mismo valor cuando se pasa a eval() , de lo contrario, la representación es una cadena entre paréntesis angulares que contiene el nombre del tipo de objeto. con información adicional que a menudo incluye el nombre y la dirección del objeto. Una clase puede controlar lo que esta función devuelve 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 las 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 da ningún argumento, devuelve la cadena vacía, '' .


A menos que actúe específicamente para garantizar que 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 la id 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 ve, si invalida __repr__ , TAMBIÉN se usa para __str__ , pero no al revés.

Otros datos importantes que debe saber: __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, a casi nadie le molesta 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ó el módulo relevante). En realidad es totalmente imposible).

Por lo tanto, mi consejo: concéntrese en hacer __str__ razonablemente legible para el ser humano, y __repr__ más inequívoco que pueda, incluso si eso interfiere con el objetivo inalcanzable de hacer que __repr__ devuelva el valor aceptable como entrada para __eval__ !


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 el objeto con la declaración de impresión.

3) En caso de que falte __str__ , imprima y cualquier función que use str() invoca a __repr__() del objeto.

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

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

6) __repr__() puede llamar a repr() que intentará evitar la recursión infinita automáticamente, reemplazando un objeto ya representado con ...


Con toda honestidad, eval(repr(obj)) nunca se usa. Si se encuentra usándolo, debe dejar de hacerlo, porque eval es peligroso y las cadenas son una manera muy ineficiente de serializar sus objetos (use pickle lugar).

Por lo tanto, recomendaría establecer __repr__ = __str__ . La razón es que str(list) llama a repr en los elementos (considero que este es uno de los mayores defectos de diseño de Python que no fue abordado por Python 3). Una repr real probablemente no será muy útil como resultado de la print [your, objects] .

Para calificar esto, en mi experiencia, el caso de uso más útil de la función repr es poner una cadena dentro de otra cadena (utilizando el formato de cadena). De esta manera, no tiene que preocuparse por escaparse de citas ni nada. Pero tenga en cuenta que no hay ninguna eval sucediendo aquí.


Desde http://pyref.infogami.com/__str__ por effbot:

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


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'

Las respuestas excelentes cubren la diferencia entre __str__ y __repr__ , que para mí se reduce a que el usuario final sea legible incluso para un usuario final, y el último es lo más útil posible para los desarrolladores. Dado esto, encuentro que la implementación predeterminada de __repr__ menudo no logra este objetivo porque omite información útil para los desarrolladores.

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

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

Mucho más claro desde el blog

Str es como toString. creado para que pueda imprimir la reproducción de datos es como serializar, o encurtir. ¿Cómo puedo recrear este objeto si necesito hacerlo usando eval ()

>>> import datetime
>>> now = datetime.datetime.now() 
>>> str(now)
'2015-04-04 20:51:31.766862'
>>> repr(now)
'datetime.datetime(2015, 4, 4, 20, 51, 31, 766862)'
>>mydate = eval(repr(now))

Para hacerlo mas simple:

__str__ se usa para mostrar una representación en cadena de su objeto para que otros puedan leerlo fácilmente .

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

Digamos que quiero crear una clase de Fraction donde la representación de la cadena de una fracción es '(1/2)' y el objeto (clase de fracción) debe representarse como 'fracción (1,2)'

Entonces podemos crear una clase de fracciones 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)

__repr__ se usa en todas partes, excepto por print y str cuando se define un __str__


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 salida para el usuario final

repr ():

  • Necesita código que reproduzca el objeto.
  • genera salida para desarrollador

Alex resumió bien pero, sorprendentemente, era demasiado breve.

Primero, permítame reiterar los puntos principales en el post de Alex :

  • La implementación predeterminada es inútil (es difícil pensar en una que no lo sería, pero sí)
  • __repr__ objetivo es ser inequívoco
  • __str__ objetivo es ser legible
  • Contenedor __str__ utiliza objetos contenidos __repr__

La implementación por defecto 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 __repr__ que actuaría como:

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

hubiera sido demasiado peligroso (por ejemplo, demasiado fácil para obtener una recursión infinita si los objetos se hacen referencia entre sí). Así que Python se va fuera. 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 implementa deben tener un __repr__ funcional que se pueda utilizar para comprender el objeto. Implementar __str__ es opcional: haga eso 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 los depuradores. Realmente no sé cómo usar ningún depurador, y nunca he usado uno en serio. Además, creo que la gran falla de los depuradores es su naturaleza básica: la mayoría de los fallos que depuro ocurrieron hace 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 de "quita y olvida". Python facilita el registro: tal vez con algunos envoltorios 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 tienes que hacer el último paso: asegúrate de que cada objeto que implementes tenga una reproducción útil, por lo que un código como ese puede funcionar. Esta es la razón por la que surge la cosa "eval": si tiene suficiente información, entonces 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 forma difusa, hazlo. Si no, asegúrate de tener suficiente información sobre c todos modos. Usualmente uso un formato similar a eval: "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 de expresar "esto es todo lo que necesita saber sobre esta instancia".

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

El objetivo de __str__ es ser legible.

Específicamente, no se pretende que sea inequívoco: observe que str(3)==str("3") . Del mismo modo, si implementa una abstracción de IP, tener el str de él 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 en que un usuario, no un programador, quiera leerlo. Corte dígitos inútiles, simule ser otra clase: mientras sea compatible con la legibilidad, es una mejora.

Contenedor __str__ utiliza objetos contenidos __repr__

Esto parece sorprendente, ¿no? Es un poco, pero lo legible sería.

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

¿ser? No muy. Específicamente, a las cadenas de un contenedor les resultaría demasiado fácil alterar su representación de cadena. Ante la ambigüedad, recuerda, Python resiste la tentación de adivinar. Si desea el comportamiento anterior cuando está imprimiendo una lista, simplemente

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

(Es probable que también puedas averiguar qué hacer con los diccionarios.

Resumen

Implementar __repr__ para cualquier clase que implementes. Esto debería ser una segunda naturaleza. Implemente __str__ si cree que sería útil tener una versión de cadena que cometa errores en el sentido de una mayor legibilidad en favor de una mayor ambigüedad.


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

Del libro: Fluent Python





repr