2013-03-28 1 views
10

Печать Python не используется __repr__, __unicode__ или __str__ для моего подкласса unicode при печати. Какие-нибудь подсказки относительно того, что я делаю неправильно?Python print не использует __repr__, __unicode__ или __str__ для юникодного подкласса?

Вот мой код:

Использование Python 2.5.2 (R252: 60911, 13 октября 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' 

Я не уверен, если это является точным приближение выше, но только для сравнения:

>>> 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) и предлагает контроль над юникодом ре включить значения, и с юникода магнезии является ...

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

_ ул _ и _ Repr _ выше ничего не добавляют к этому примеру, но идея состоит в том, чтобы показать образец явно , которые должны быть расширены по мере необходимости.

Просто, чтобы доказать, что эта модель предоставляет контроль:

>>> 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) возвращает истину, если тип v «s является unicodeили подкласс. Поэтому этот код записывает объекты unicode напрямую, без консультации __str__.

Обратите внимание, что подклассы str и наиважнейшая __str__ работы, как и ожидалось:

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

как это делает вызова str или 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' 

Я считаю, что это может быть истолковано как ошибка в Python, как в настоящее время реализованы.

6

Вы являетесь подклассом unicode.

Он никогда не позвонит __unicode__, потому что он уже есть unicode. То, что происходит здесь, вместо того, что объект является кодируются к stdout кодирования:

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

за исключением того, что он будет использовать прямой C вызывает вместо метода .encode(). Это поведение по умолчанию для print для объектов unicode.

Заявление print вызывает PyFile_WriteObject, которое, в свою очередь, вызывает PyUnicode_AsEncodedString при обращении к объекту unicode. Затем последний отбрасывает функцию кодирования для текущей кодировки, и они используют Unicode C macros для прямого доступа к структурам данных. Вы не можете перехватить это из Python.

Что вы ищете, это крючок __encode__, я думаю. Так как это уже подкласс unicode, print нужно только для кодирования, а не для его преобразования в unicodeснова, а также не может преобразовать его в строку без его кодировки явно. Вам нужно будет обсудить это с основными разработчиками Python, чтобы узнать, имеет ли смысл __encode__.

+0

Поскольку это не относится к подклассам 'str', я думаю, что это ошибка Python. См. Мой ответ. – nneonneo

+1

@nneonneo: не уверен, что я все еще согласен. :-) –

+1

Хм, почему бы это не быть ошибкой? Лечение 'str' и' unicode' должно быть относительно однородным в Python 2.7. – nneonneo

Смежные вопросы