python example - Diferencia entre __str__ y __repr__?




metodo (18)

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


Answers

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

>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

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


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

  • El __repr__ apunta a una representación de cadena completa del objeto;
  • El __str__ es devolver una cadena agradable para imprimir.

Por eso, prefiero entenderlos como

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

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

Un ejemplo pequeño pero bueno también se da 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'

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

Una cosa importante a tener en cuenta es que el __str__ contenedor utiliza los objetos __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 llamada __str__ de una tuple llama a __repr__ los objetos contenidos, 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.


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


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

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

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


Mi regla de oro: __repr__ es para desarrolladores, __str__ es para clientes.


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


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__ : no ambiguo, posiblemente legible por máquina a través de eval

Desafortunadamente, esta diferenciación es defectuosa, porque el REPL de Python y también el IPython utilizan __repr__ para imprimir objetos en una consola REPL (consulte las preguntas relacionadas con Python e IPython ). Por lo tanto, los proyectos dirigidos al trabajo de la consola interactiva (p. Ej., Numpy o Pandas) han comenzado a ignorar las reglas anteriores y proporcionar una implementación __repr__ legible para el __repr__ .


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

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


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


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


Comprenda __str__ y __repr__ intuitiva y permanentemente, distingalas en absoluto.

__str__ devuelve la cadena disfrazada del cuerpo de un objeto dado para que sea legible de los ojos
__repr__ devuelve el cuerpo de carne real de un objeto determinado (se devuelve a sí mismo) para que no se identifique la ambigüedad.

Véalo 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 en __repr__ resultados convenientemente.

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.


x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z

Para los elementos con claves en ambos diccionarios ('b'), puede controlar cuál de ellos termina en la salida colocando ese último.





python magic-methods repr