¿La impresión de Python no está utilizando __repr__, __unicode__ o __str__ para la subclase de Unicode?

La impresión de Python no está utilizando __repr__ , __unicode__ o __str__ para mi subclase de Unicode al imprimir. ¿Alguna pista en cuanto a lo que estoy haciendo mal?

Aquí está mi código:

Utilizando Python 2.5.2 (r252: 60911, 13 de octubre de 2009, 14:11:59)

 >>> class MyUni(unicode): ... def __repr__(self): ... return "__repr__" ... def __unicode__(self): ... return unicode("__unicode__") ... def __str__(self): ... return str("__str__") ... >>> s = MyUni("HI") >>> s '__repr__' >>> print s 'HI' 

No estoy seguro de si esta es una aproximación precisa de lo anterior, pero solo para comparación:

 >>> class MyUni(object): ... def __new__(cls, s): ... return super(MyUni, cls).__new__(cls) ... def __repr__(self): ... return "__repr__" ... def __unicode__(self): ... return unicode("__unicode__") ... def __str__(self): ... return str("__str__") ... >>> s = MyUni("HI") >>> s '__repr__' >>> print s '__str__' 

[EDITADO …] Suena como la mejor manera de obtener un objeto de cadena que es instancia (instancia, cadena de base) y ofrece control sobre los valores de retorno de Unicode, y con una reproducción de Unicode es …

 >>> class UserUnicode(str): ... def __repr__(self): ... return "u'%s'" % super(UserUnicode, self).__str__() ... def __str__(self): ... return super(UserUnicode, self).__str__() ... def __unicode__(self): ... return unicode(super(UserUnicode, self).__str__()) ... >>> s = UserUnicode("HI") >>> s u'HI' >>> print s 'HI' >>> len(s) 2 

Las _ str _ y _ repr_ anteriores no agregan nada a este ejemplo, pero la idea es mostrar un patrón explícitamente, para extenderse según sea necesario.

Solo para probar que este patrón otorga control:

 >>> class UserUnicode(str): ... def __repr__(self): ... return "u'%s'" % "__repr__" ... def __str__(self): ... return "__str__" ... def __unicode__(self): ... return unicode("__unicode__") ... >>> s = UserUnicode("HI") >>> s u'__repr__' >>> print s '__str__' 

¿Pensamientos?

El problema es que la print no respeta __str__ en unicode subclases de unicode .

De PyFile_WriteObject , utilizado por print :

 int PyFile_WriteObject(PyObject *v, PyObject *f, int flags) { ... if ((flags & Py_PRINT_RAW) && PyUnicode_Check(v) && enc != Py_None) { char *cenc = PyString_AS_STRING(enc); char *errors = fobj->f_errors == Py_None ? "strict" : PyString_AS_STRING(fobj->f_errors); value = PyUnicode_AsEncodedString(v, cenc, errors); if (value == NULL) return -1; 

PyUnicode_Check(v) devuelve true si el tipo de v es unicode o una subclase . Por lo tanto, este código escribe objetos Unicode directamente, sin consultar a __str__ .

Tenga en cuenta que la subclasificación de str y la anulación de __str__ funcionan como se esperaba:

 >>> class mystr(str): ... def __str__(self): return "str" ... def __repr__(self): return "repr" ... >>> print mystr() str 

así como llamar explícitamente a str o unicode :

 >>> class myuni(unicode): ... def __str__(self): return "str" ... def __repr__(self): return "repr" ... def __unicode__(self): return "unicode" ... >>> print myuni() >>> str(myuni()) 'str' >>> unicode(myuni()) u'unicode' 

Creo que esto podría interpretarse como un error en Python como se implementa actualmente.

Estás subclasificando unicode .

Nunca llamará __unicode__ porque ya es unicode. Lo que sucede aquí, en cambio, es que el objeto está codificado en la encoding stdout :

 >>> s.encode('utf8') 'HI' 

excepto que usará llamadas directas en C en lugar del método .encode() . Este es el comportamiento predeterminado para print para objetos Unicode.

La statement de print llama a PyFile_WriteObject , que a su vez llama a PyUnicode_AsEncodedString cuando maneja un objeto unicode . Este último luego pasa a una función de encoding para la encoding actual, y éstas utilizan las macros Unicode C para acceder directamente a las estructuras de datos. No puedes interceptar esto desde Python.

Lo que estás buscando es un gancho __encode__ , supongo. Dado que esto ya es una subclase de unicode , la print solo necesita codificarse, no volver a convertirla a unicode , ni puede convertirla a cadena sin codificarla explícitamente. Tendría que abordar esto con los desarrolladores centrales de Python, para ver si un __encode__ tiene sentido.