Справочник по языку Python 1002 * имеет ответ:
Если format
является объектом Unicode или если какой-либо из объектов, преобразованных с помощью преобразования %s
, является объектом Unicode, результатом также будет объект Unicode.
foo = u'Émilie and Juañ are turncoats.'
bar = "foo is %s" % foo
Это работает, потому что foo
является unicode
объектом. Это приводит к тому, что приведенное выше правило вступает в силу, и в результате получается строка Unicode.
bar = "foo2 is %s" % foo2
В этом случае foo2
- это объект Exception
, который явно не является unicode
объектом. Поэтому интерпретатор пытается преобразовать его в обычный str
, используя кодировку по умолчанию. Это, по-видимому, ascii
, который не может представлять эти символы и выручает за исключением.
bar = u"foo2 is %s" % foo2
Здесь это снова работает, потому что строка формата - это unicode
объект. Таким образом, интерпретатор также пытается преобразовать foo2
в unicode
объект, что успешно.
Что касается вопроса Рэндалла: это меня тоже удивляет. Однако это равно в соответствии со стандартом (переформатировано для удобства чтения):
%s
преобразует любой объект Python, используя str()
. Если предоставленный объект или формат - строка unicode
, результирующая строка также будет unicode
.
Как создается такой unicode
объект, остается неясным. Так что оба законны:
- вызов
__str__
, декодирование обратно в строку Unicode и вставка ее в строку вывода
- вызовите
__unicode__
и вставьте результат непосредственно в строку вывода
Смешанное поведение интерпретатора Python действительно довольно отвратительно. Я бы посчитал это ошибкой в стандарте.
Редактировать: Цитировать Python 3.0 журнал изменений , выделение:
Все, что вы думали о двоичных данных и Unicode, изменилось.
[...]
- Как следствие этого изменения в философии, почти весь код, который использует Unicode, кодировки или двоичные данные, скорее всего, должен измениться. Изменения к лучшему, поскольку в мире 2.x было многочисленных ошибок, связанных с смешиванием закодированного и незашифрованного текста .