Python print не использует repr, unicode или str для подкласса unicode?
Python print не использует __repr__, __unicode__ или __str__ для моего подкласса unicode при печати. Есть какие-нибудь намеки на то, что я делаю не так?
Вот мой код:
Использование Python 2.5.2 (r252:60911, Oct 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) и предлагает контроль над возвращением unicode значения, и с юникодом repr есть...
>>> 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
_ str_ и еще _репр_ выше ничего не добавлено к этому примеру, но идея состоит в том, чтобы показать шаблон явно, чтобы быть расширенным по мере необходимости.
Просто чтобы доказать, что этот паттерн дает контроль:
>>> 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__'
Мысли?
2 ответов:
Проблема в том, что
__str__наunicodeподклассах.От
PyFile_WriteObject, используется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Как и вызов
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, как это реализовано в настоящее время.
Вы подклассы
unicode.Он никогда не вызовет
__unicode__, потому что он уже является unicode. Вместо этого здесь происходит то, что объект кодируется в кодировкуstdout:>>> s.encode('utf8') 'HI'За исключением того, что он будет использовать прямые вызовы C вместо метода
.encode(). Это поведение по умолчанию дляОператор
То, что вы ищете, - это крючокPyFile_WriteObject, что в свою очередь вызываетPyUnicode_AsEncodedStringпри работе с объектомunicode. Тогда последнее переносится на функцию кодирования для текущей кодировки, и они используют макросы Unicode C для прямого доступа к структурам данных. Вы не можете перехватить это у Python.__encode__, я думаю. Поскольку это уже подклассunicode,unicodeопять же , и он не может преобразовать его в строку, не кодируя его явно. Вам придется обсудить это с разработчиками ядра Python, чтобы увидеть, имеет ли__encode__смысл.
Comments