Поскольку в этом вопросе много запутанного юникодного материала, я подумал, что предложу анализ того, что здесь происходит.
Все сводится к реализации __unicode__
и __repr__
встроенного класса list
. В основном это эквивалентно:
class list(object):
def __repr__(self):
return "[%s]" % ", ".join(repr(e) for e in self.elements)
def __str__(self):
return repr(self)
def __unicode__(self):
return str(self).decode()
На самом деле, list
даже не определяет __unicode__
и __str__
методы , что имеет смысл, когда вы об этом думаете.
Когда вы пишете:
u"%s" % [a] # it expands to
u"%s" % unicode([a]) # which expands to
u"%s" % repr([a]).decode() # which expands to
u"%s" % ("[%s]" % repr(a)).decode() # (simplified a little bit)
u"%s" % ("[%s]" % unicode(a).encode('utf-8')).decode()
Эта последняя строка является расширением repr (a) с использованием реализации __repr__
в вопросе.
Итак, как вы можете видеть, объект сначала кодируется в utf-8, а затем декодируется с использованием системной кодировки по умолчанию, которая обычно не поддерживает все символы.
Как уже упоминалось в некоторых других ответах, вы можете написать свою собственную функцию или даже список подклассов, например:
class mylist(list):
def __unicode__(self):
return u"[%s]" % u", ".join(map(unicode, self))
Обратите внимание, что этот формат не допускает циклическое переключение. Это может даже вводить в заблуждение:
>>> unicode(mylist([]))
u'[]'
>>> unicode(mylist(['']))
u'[]'
Конечно, вы можете написать quote_unicode
функцию, чтобы сделать ее способной к круговому переключению, но сейчас самое время спросить себя в чем смысл . Функции unicode
и str
предназначены для создания представления объекта, которое имеет смысл для пользователя. Для программистов есть функция repr
. Необработанные списки - это не то, что пользователь когда-либо должен видеть. Вот почему класс list
не реализует метод __unicode__
.
Чтобы получить лучшее представление о том, что происходит, поиграйте с этим небольшим классом:
class B(object):
def __unicode__(self):
return u"unicode"
def __repr__(self):
return "repr"
def __str__(self):
return "str"
>>> b
repr
>>> [b]
[repr]
>>> unicode(b)
u'unicode'
>>> unicode([b])
u'[repr]'
>>> print b
str
>>> print [b]
[repr]
>>> print unicode(b)
unicode
>>> print unicode([b])
[repr]