2013-03-28 99 views
10

蟒紋不使用__repr____unicode____str__我的Unicode的子類。任何線索,我做錯了什麼?Python打印不使用__repr__,__unicode__或__str__爲unicode子類?打印時

這裏是我的代碼:

使用Python 2.5.2(R252:60911,2009年10月13日,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' 

我不知道這是否是一個正確的上述的近似,但只是比較:

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

將帖子...] 這聽起來像得到一個字符串對象的最佳方式,isinstance(例如,即basestring),並提供了統一重新控制轉值,並使用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 

_ 海峽 __ 再版 _上面沒有加入到這個例子,但這個想法是明確的顯示模式,根據需要進行擴展。

只是爲了證明,這種模式賦予控制:

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

的思考?

+1

你的代碼是否真的像第一個例子一樣縮進? – GreenMatt

+1

我不得不猜測你的問題是什麼。如果我認爲它錯了,請更新您的帖子,*包括一個實際的,明確的問題*。 –

+0

儘管這是一個很好的陷阱,但我想問一下,爲什麼在h ***中想要繼承str或unicode?我的意思是,數據將是不可變的,所以它產生的對象將是無用的。 – kay

回答

10

問題是print不尊重__str__unicode子類。

PyFile_WriteObject,通過使用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)返回true v的類型是unicode或子類。因此,此代碼直接寫入unicode對象,而無需諮詢__str__

注意,子類str和壓倒一切的__str__按預期工作:

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

一樣調用strunicode明確:

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

我相信這可以被解釋爲Python作爲當前的錯誤實現。

6

你繼承unicode

它永遠不會撥打__unicode__,因爲它已經是 unicode。什麼,而不是在這裏發生的是,對象是編碼stdout編碼:

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

但它會使用直接的C調用,而不是.encode()方法。這是針對unicode對象的print的默認行爲。

print聲明調用PyFile_WriteObject,在處理unicode對象時又調用PyUnicode_AsEncodedString。後者然後根據當前編碼推遲編碼函數,並且這些編碼函數使用Unicode C macros直接訪問數據結構。你不能從Python中截取這個。

你所尋找的是一個__encode__鉤,我猜。由於這已經是一個unicode子類,print只需要編碼,而不是將其轉換爲unicode再次,也無法將其轉換爲字符串,但沒有明確對其進行編碼。你必須和Python核心開發人員一起來看看__encode__是否合理。

+0

既然它不爲'str'子類做這件事,我認爲這是一個Python bug。看到我的答案。 – nneonneo

+1

@nneonneo:不確定我是否同意。 :-) –

+1

嗯,爲什麼它不是一個錯誤?在Python 2.7中處理'str'和'unicode'應該是相對統一的。 – nneonneo