Me parece que las funciones integradas __repr__ y __str__ tienen una diferencia importante en su definición base.

>>> t2 = u'\u0131\u015f\u0131k'
>>> print t2
ışık
>>> t2
Out[0]: u'\u0131\u015f\u0131k'

t2.decode genera un error ya que t2 es una cadena unicode.

>>> enc = 'utf-8'
>>> t2.decode(enc)
------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
  File "C:\java\python\Python25\Lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordin
al not in range(128)

__str__ genera un error como si se llamara a la función decode():

>>> t2.__str__()
------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordin
al not in range(128)

Pero __repr__ funciona sin problema:

>>> t2.__repr__()
Out[0]: "u'\\u0131\\u015f\\u0131k'"

¿Por qué __str__ produce un error mientras que __repr__ funciona correctamente?

Esta pequeña diferencia parece causar un error en una aplicación de Django en la que estoy trabajando.

0
Mert Nuhoglu 12 ago. 2009 a las 22:03

4 respuestas

La mejor respuesta

Básicamente, __str__ solo puede generar cadenas ASCII. Dado que t2 contiene puntos de código unicode sobre ascii, no se puede representar con solo una cadena. __repr__, por otro lado, intenta generar el código python necesario para recrear el objeto. Verá que la salida de repr (t2) (esta sintaxis se prefiere a t2.__repr_()) es exactamente lo que establece t2 igual a arriba en la primera línea. El resultado de repr se parece más o menos a ['\', 'u', '0', ...], que son todos valores ascii, pero la salida de str intenta ser [chr (0x0131), chr (0x015f) , chr (0x0131), 'k'], la mayoría de los cuales están por encima del rango de caracteres aceptable en una cadena de Python. En general, cuando se trata de aplicaciones django, debe usar __unicode__ para todo y nunca tocar __str__.

Más información en la documentación de django en cadenas.

7
Michael Fairley 12 ago. 2009 a las 18:20

Tenga en cuenta que en Python 3, unicode es el valor predeterminado, y __str__() siempre debería proporcionarle unicode.

0
SilentGhost 12 ago. 2009 a las 21:10

Para agregar un poco de apoyo a la buena respuesta de John:

Para entender la denominación de los dos métodos encode () y decode () , solo tiene que ver que Python considera cadenas unicode de la forma u '.. . ' para estar en el formato de referencia . Usted codifica pasando del formato de referencia a otro formato (por ejemplo, utf-8), y decodificando desde algún otro formato para llegar al formato de referencia. El formato Unicode siempre se considera "real" :-).

2
Pi Delport 29 ene. 2012 a las 10:10

En general, llamar a str.__unicode__() o unicode.__str__() es una muy mala idea, porque los bytes no se pueden convertir de forma segura en puntos de caracteres Unicode y viceversa. La excepción son los valores ASCII, que generalmente son los mismos en todas las codificaciones de un solo byte. El problema es que está utilizando el método incorrecto para la conversión.

Para convertir unicode a str, debe usar encode():

>>> t1 = u"\u0131\u015f\u0131k"
>>> t1.encode("utf-8")
'\xc4\xb1\xc5\x9f\xc4\xb1k'

Para convertir str a unicode, use decode():

>>> t2 = '\xc4\xb1\xc5\x9f\xc4\xb1k'
>>> t2.decode("utf-8")
u'\u0131\u015f\u0131k'
5
John Millikin 12 ago. 2009 a las 18:34