2009-08-20 12 views
182

Existe una convención de python para cuándo debe implementar __str__() frente a __unicode__(). He visto las clases anular __unicode__() con más frecuencia que __str__() pero no parece ser consistente. ¿Existen reglas específicas cuando es mejor implementar una versus la otra? ¿Es necesario/buena práctica implementar ambos?Python __str__ versus __unicode__

Respuesta

227

__str__() es el método anterior - devuelve bytes. __unicode__() es el nuevo método preferido: devuelve caracteres. Los nombres son un poco confusos, pero en 2.x estamos atrapados por razones de compatibilidad. En general, debe poner toda su cadena de formato en __unicode__(), y crear un talón __str__() método:

def __str__(self): 
    return unicode(self).encode('utf-8') 

En 3.0, str contiene caracteres, por lo que los mismos métodos se denominan __bytes__() y __str__(). Estos se comportan como se esperaba.

+1

sa quiere decir crear métodos __unicode__ y __str__ o simplemente mantener cadenas en _ (u "") y crear __string__ (sin el método Unicode)? – muntu

+9

¿Hay algún error al implementar solo uno de ellos? ¿Qué sucede cuando solo implementa '' __unicode__' y luego '' str (obj) '? – RickyA

+9

'unicode' plantea un' NameError' en Python 3, ¿es un patrón simple que funciona tanto en 2 como en 3? –

9

Con el mundo cada vez más pequeño, es probable que cualquier cadena que encuentre contenga Unicode eventualmente. Entonces, para cualquier aplicación nueva, al menos debe proporcionar __unicode__(). Si usted también reemplaza __str__() es simplemente una cuestión de gusto.

19

Si no me preocupa especialmente la stringificación de micro-optimización para una clase determinada, siempre implementaría __unicode__ solo, ya que es más general. Cuando me importan los problemas de rendimiento tan pequeños (que es la excepción, no la regla), tengo __str__ solamente (cuando puedo demostrar que nunca habrá caracteres que no sean ASCII en el resultado codificado) o ambos (cuando ambos son posibles), podría ayudar.

Creo que estos son principios sólidos, pero en la práctica es muy común SABER que no habrá nada más que caracteres ASCII sin esfuerzo para probarlo (por ejemplo, la forma en cadena solo tiene dígitos, puntuación y tal vez un nombre corto ASCII; -) en cuyo caso es bastante típico pasar directamente al enfoque "solo __str__" (pero si un equipo de programación con el que trabajé propuso una guía local para evitar eso, estaría +1 en la propuesta, ya que es fácil err en estos asuntos Y "la optimización prematura es la raíz de todo mal en la programación" ;-).

+2

en Python 2.6.2, hace poco tuvo un tropiezo, porque los casos de una subclase Exception incorporada en particular dio resultados diferentes con str (e) y unicode (e). str (e) dio salida fácil de usar; Unicode (e) dio salida diferente, poco amigable para el usuario. ¿Esto se considera un comportamiento defectuoso? La clase es UnicodeDecodeError; No lo mencioné por adelantado para evitar confusiones; el hecho de que la excepción esté relacionada con Unicode no es particularmente relevante. –

0

Si está trabajando tanto en python2 y python3 en Django, recomiendo el decorador python_2_unicode_compatible:

Django proporciona una forma sencilla de definir str() y Unicode() métodos que funcionan en Python 2 y 3: debe definir un método str() que devuelve texto y aplicar el decodificador python_2_unicode_compatible().

Como se señaló en los comentarios anteriores a otra respuesta, algunas versiones de future.utils también admiten este decorador. En mi sistema, necesitaba instalar un módulo futuro más nuevo para python2 e instalar future para python3. Después de eso, entonces aquí es un ejemplo funcional:

#! /usr/bin/env python 

from future.utils import python_2_unicode_compatible 
from sys import version_info 

@python_2_unicode_compatible 
class SomeClass(): 
    def __str__(self): 
     return "Called __str__" 


if __name__ == "__main__": 
    some_inst = SomeClass() 
    print(some_inst) 
    if (version_info > (3,0)): 
     print("Python 3 does not support unicode()") 
    else: 
     print(unicode(some_inst)) 

Aquí es una salida de ejemplo (donde venv2/venv3 son casos virtualenv):

~/tmp$ ./venv3/bin/python3 demo_python_2_unicode_compatible.py 
Called __str__ 
Python 3 does not support unicode() 

~/tmp$ ./venv2/bin/python2 demo_python_2_unicode_compatible.py 
Called __str__ 
Called __str__ 
Cuestiones relacionadas