2013-03-28 8 views
10

La stampa Python non utilizza __repr__, __unicode__ o __str__ per la sottoclasse unicode durante la stampa. Qualche indizio su cosa sto facendo male?La stampa Python non sta utilizzando __repr__, __unicode__ o __str__ per la sottoclasse unicode?

Ecco il mio codice:

Usare Python 2.5.2 (R252: 60911, 13 Ottobre, 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' 

io non sono sicuro se questo è un accurato approssimazione di quanto sopra, ma solo per il confronto:

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

[Modificato ...] suona come il modo migliore per ottenere un oggetto stringa che isinstance (esempio, basestring) e offre il controllo su unicode re girare valori, e con un rist unicode è ...

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

Il _ str _ e _ repr _ sopra aggiungere nulla a questo esempio, ma l'idea è di mostrare un modello esplicitamente , da estendere secondo necessità.

solo per dimostrare che questo schema garantisce il controllo:

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

Pensieri?

+1

Il tuo codice è davvero rientrato come il primo esempio? – GreenMatt

+1

Ho dovuto indovinare qual è la tua domanda. Se ho sbagliato, per favore aggiorna il tuo messaggio in * includi una domanda reale e chiara *. –

+0

Anche se questo è un bel trucco, vorrei chiedere perché in h *** ti piacerebbe sottoclasse str o unicode? Voglio dire, i dati saranno immutabili, quindi l'oggetto risultante sarà abbastanza inutile. – kay

risposta

10

Il problema è che print non rispetta le sottoclassi __str__ su unicode.

Da PyFile_WriteObject, usato da 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) restituisce vero se il tipo v s' è unicodeo una sottoclasse. Questo codice quindi scrive direttamente oggetti Unicode, senza consultare __str__.

noti che sottoclassi str e prioritario __str__ funziona come previsto:

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

come fa chiamare str o unicode esplicitamente:

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

Credo che questo potrebbe essere interpretato come un bug in Python come attualmente implementato.

6

La sottoclasse è unicode.

Non chiamerà mai __unicode__ perché è già unicode. Quello che succede qui invece è che l'oggetto è codificato alla codifica stdout:

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

tranne che userà diretta C chiama anziché il metodo .encode(). Questo è il comportamento predefinito per print per oggetti Unicode.

L'istruzione print chiama PyFile_WriteObject, che a sua volta chiama PyUnicode_AsEncodedString quando gestisce un oggetto unicode. Quest'ultimo quindi rimanda a una funzione di codifica per la codifica corrente e questi utilizzano lo Unicode C macros per accedere direttamente alle strutture di dati. Non puoi intercettarlo da Python.

Quello che stai cercando è un gancio __encode__, credo. Poiché questa è già una sottoclasse unicode, è necessario codificare print, non convertirlo in unicodedi nuovo, né convertirlo in stringa senza codificarlo esplicitamente. Dovresti prendere questo con gli sviluppatori core di Python, per vedere se un __encode__ ha senso.

+0

Dato che non lo fa per le sottoclassi di 'str', penso che questo sia un bug Python. Vedi la mia risposta. – nneonneo

+1

@nneonneo: non sono sicuro di essere d'accordo ancora. :-) –

+1

Hm, perché non sarebbe un bug? Il trattamento di 'str' e' unicode' dovrebbe essere relativamente uniforme in Python 2.7. – nneonneo

Problemi correlati