Работая с Python 2.7, мне интересно, какое реальное преимущество дает использование типа unicode
вместо str
, поскольку оба они, похоже, могут содержать строки Unicode. Есть ли какая-то особая причина, кроме возможности устанавливать коды Unicode в unicode
строках с помощью escape-символа \
?:
Выполнение модуля с помощью:
# -*- coding: utf-8 -*-
a = 'á'
ua = u'á'
print a, ua
Результаты в: á, á
РЕДАКТИРОВАТЬ:
Дополнительное тестирование с использованием оболочки Python:
>>> a = 'á'
>>> a
'\xc3\xa1'
>>> ua = u'á'
>>> ua
u'\xe1'
>>> ua.encode('utf8')
'\xc3\xa1'
>>> ua.encode('latin1')
'\xe1'
>>> ua
u'\xe1'
Итак, unicode
кажется , что строка кодируется с использованием latin1
вместо, utf-8
а необработанная строка кодируется с помощью utf-8
? Я запуталась еще больше! : S
unicode
, это просто абстракция символа Юникода;unicode
можно преобразовать вstr
некоторую кодировку (напримерutf-8
).Ответы:
unicode
предназначен для обработки текста . Текст - это последовательность кодовых точек, размер которых может превышать один байт . Текст может быть закодирован в определенной кодировке для представления текста в виде необработанных байтов (напримерutf-8
,latin-1
...).Обратите внимание, что
unicode
не кодируется ! Внутреннее представление, используемое python, является деталью реализации, и вы не должны беспокоиться об этом, если оно может представлять нужные вам точки кода.Напротив,
str
в Python 2 есть простая последовательность байтов . Это не текст!Вы можете думать об этом
unicode
как об общем представлении некоторого текста, который можно разными способами закодировать в последовательность двоичных данных, представленных черезstr
.Примечание. В Python 3 он
unicode
был переименован вstr
и появился новыйbytes
тип для простой последовательности байтов.Некоторые различия, которые вы можете увидеть:
Обратите внимание, что при использовании у
str
вас есть элемент управления нижнего уровня для отдельных байтов определенного представления кодировки, в то время как при использованииunicode
вы можете управлять только на уровне кодовой точки. Например, вы можете:То, что раньше было действительным UTF-8, больше не существует. Используя строку Unicode, вы не можете работать таким образом, чтобы результирующая строка не была допустимым текстом Unicode. Вы можете удалить кодовую точку, заменить кодовую точку другой кодовой точкой и т. Д., Но вы не можете вмешиваться во внутреннее представление.
источник
unicode
объектов, я думаю, мы сначала должны явно указатьencode()
им правильный формат кодирования, поскольку мы не знаем, какой из них используется внутри для представленияunicode
значения.unicode
объект.unicode
которое не закодировано, явно неверно. UTF-16 / UCS-2 и UTF-32 / UCS-4 также являются кодировками ... и в будущем, возможно, их будет создано больше. Дело в том, что то, что вы не должны заботиться о деталях реализации (и, действительно, не должны!), Это еще не означает, чтоunicode
это не закодировано. Конечно, есть. Может ли это быть.decode()
- совсем другая история.unicode
внутреннее представление объекта может быть любым, в том числе нестандартным. В частности , в Python3 +unicode
действительно использовать нестандартное внутреннее представление , что также изменяется в зависимости от данных , содержащееся. Таким образом, это не стандартная кодировка . Unicode как текстовый стандарт определяет только кодовые точки, которые являются абстрактным представлением текста, существует множество способов кодирования Unicode в памяти, включая стандартный utf-X и т. Д. Python использует свой собственный способ для повышения эффективности.unicode
объектом CPython , поскольку он не использует ни UTF-16, ни UTF-32. Он использует специальное представление, и если вы хотите закодировать данные в фактические байты, вы должны использоватьencode
. Также: язык не определяет, какunicode
реализован, поэтому разные версии или реализации python могут (и имеют ) разное внутреннее представление.Юникод и кодировки - совершенно разные, не связанные между собой вещи.
Unicode
Присваивает числовой идентификатор каждому символу:
Итак, Unicode присваивает номер 0x41 для A, 0xE1 для á и 0x414 для Д.
Даже маленькая стрелка →, которую я использовал, имеет свой номер в Юникоде, это 0x2192. И даже у смайликов есть номера в Юникоде, 😂 - это 0x1F602.
Вы можете посмотреть номера Unicode всех символов в этой таблице . В частности, вы можете найти первые три символа выше здесь , стрелка здесь , и смайликов здесь .
Эти номера, присвоенные всем символам Unicode, называются кодовыми точками .
Цель всего этого - предоставить средства для однозначной ссылки на каждый символ. Например, если я говорю о 😂, вместо того, чтобы сказать «ну вы знаете, этот смеющийся смайлик со слезами» , я могу просто сказать кодовая точка Unicode 0x1F602 . Легче, правда?
Обратите внимание, что кодовые точки Unicode обычно форматируются в начале
U+
, а затем шестнадцатеричное числовое значение дополняется как минимум до 4 цифр. Итак, приведенные выше примеры будут: U + 0041, U + 00E1, U + 0414, U + 2192, U + 1F602.Кодовые точки Unicode варьируются от U + 0000 до U + 10FFFF. Это 1114 112 номеров. 2048 из этих номеров используются для суррогатов , таким образом, осталось 1 112 064. Это означает, что Unicode может назначить уникальный идентификатор (кодовую точку) для 1112 064 различных символов. Еще не все эти кодовые точки присвоены символу, а Unicode постоянно расширяется (например, когда вводятся новые смайлы).
Важно помнить, что все, что делает Unicode, - это присваивает каждому символу числовой идентификатор, называемый кодовой точкой, для простой и однозначной ссылки.
Кодировки
Сопоставьте символы с битовыми шаблонами.
Эти битовые комбинации используются для представления символов в памяти компьютера или на диске.
Существует множество различных кодировок, охватывающих разные подмножества символов. В англоязычном мире наиболее распространены следующие кодировки:
ASCII
Преобразует 128 символов (кодовые точки U + 0000 в U + 007F) в битовые комбинации длиной 7.
Пример:
Вы можете увидеть все сопоставления в этой таблице .
ISO 8859-1 (также известный как Latin-1)
Отображает 191 символ (кодовые точки от U + 0020 до U + 007E и от U + 00A0 до U + 00FF) в битовые комбинации длиной 8.
Пример:
Вы можете увидеть все сопоставления в этой таблице .
UTF-8
Карты 1,112,064 символов (все существующее Unicode точки коды) битовые паттерны либо длина 8, 16, 24 или 32 бит (то есть, 1, 2, 3 или 4 байта).
Пример:
Кстати UTF-8 кодирует символы в битовые строки очень хорошо описано здесь .
Юникод и кодировки
Глядя на приведенные выше примеры, становится ясно, насколько полезен Unicode.
Например, если я Latin-1 и хочу объяснить свою кодировку á, мне не нужно говорить:
Но я могу просто сказать:
И если я UTF-8 , я могу сказать:
И всем однозначно ясно, о каком персонаже идет речь.
Теперь к часто возникающей путанице
Верно, что иногда битовый шаблон кодировки, если вы интерпретируете его как двоичное число, совпадает с кодовой точкой Unicode этого символа.
Например:
Конечно, это сделано специально для удобства. Но вы должны смотреть на это как на чистое совпадение . Битовый шаблон, используемый для представления символа в памяти, никаким образом не привязан к кодовой точке Unicode этого символа.
Никто даже не говорит, что битовую строку типа 11100001 нужно интерпретировать как двоичное число. Просто посмотрите на это как на последовательность битов, которые Latin-1 использует для кодирования символа á .
Вернуться к вашему вопросу
Ваш интерпретатор Python использует кодировку UTF-8 .
Вот что происходит в ваших примерах:
Пример 1
Следующее кодирует символ á в UTF-8. В результате получается битовая строка 11000011 10100001, которая сохраняется в переменной
a
.Когда вы смотрите на значение
a
, его содержимое 11000011 10100001 форматируется как шестнадцатеричное число 0xC3 0xA1 и выводится как'\xc3\xa1'
:Пример 2
Следующее сохраняет кодовую точку Unicode для á, которая является U + 00E1, в переменной
ua
(мы не знаем, какой формат данных Python использует внутри для представления кодовой точки U + 00E1 в памяти, и это неважно для нас):Когда вы смотрите на значение
ua
, Python сообщает вам, что оно содержит кодовую точку U + 00E1:Пример 3
Следующее кодирует кодовую точку Unicode U + 00E1 (представляющую символ á) с помощью UTF-8, что приводит к битовому шаблону 11000011 10100001. Опять же, для вывода этот битовый шаблон представлен как шестнадцатеричное число 0xC3 0xA1:
Пример 4
Следующее кодирует кодовую точку Unicode U + 00E1 (представляющую символ á) с помощью Latin-1, что приводит к битовому шаблону 11100001. Для вывода этот битовый шаблон представлен как шестнадцатеричное число 0xE1, которое по совпадению совпадает с исходным кодовая точка U + 00E1:
Нет связи между объектом Unicode
ua
и кодировкой Latin-1. То, что кодовая точка á - U + 00E1, а кодировка Latin-1 для á - 0xE1 (если вы интерпретируете битовый шаблон кодирования как двоичное число), является чистым совпадением.источник
Ваш терминал настроен на UTF-8.
То, что полиграфия
a
работает - случайность; вы записываете на терминал необработанные байты UTF-8.a
представляет собой значение длины два , содержащее два байта, шестнадцатеричные значения C3 и A1, аua
представляет собой значение Unicode длины один , содержащее кодовую точку U + 00E1.Эта разница в длине - одна из основных причин использования значений Unicode; вы не можете легко измерить количество текстовых символов в байтовой строке;
len()
строки байт говорят вам , как были использованы много байт, а не как было закодированы много символов.Вы можете увидеть разницу , когда вы закодировать значение Юникода для различных выходных кодировок:
Обратите внимание, что первые 256 кодовых точек стандарта Unicode соответствуют стандарту Latin 1, поэтому кодовая точка U + 00E1 кодируется в Latin 1 как байт с шестнадцатеричным значением E1.
Кроме того, Python использует escape-коды в представлениях как юникодовых, так и байтовых строк, а младшие кодовые точки, которые не печатаются ASCII, также представлены с помощью
\x..
escape-значений. Вот почему строка Unicode с кодовой точкой от 128 до 255 выглядит так же, как кодировка Latin 1. Если у вас есть строка Unicode с кодовыми точками за пределами U + 00FF,\u....
вместо нее используется другая escape-последовательность с четырехзначным шестнадцатеричным значением.Похоже, вы еще не до конца понимаете, в чем разница между Unicode и кодировкой. Пожалуйста, прочтите следующие статьи, прежде чем продолжить:
Абсолютный минимум, который должен знать каждый разработчик программного обеспечения о Unicode и наборах символов (без оправданий!) Джоэл Спольски
Руководство по Python Unicode
Прагматический Юникод от Неда Батчелдера
источник
\xe1
латинице 1.Когда вы определяете a как unicode, символы a и á равны. В противном случае á считается как два символа. Попробуйте len (a) и len (au). В дополнение к этому вам может потребоваться кодировка при работе с другими средами. Например, если вы используете md5, вы получите разные значения для a и ua
источник