Юникод и кодировки - совершенно разные, не связанные между собой вещи.
Unicode
Присваивает числовой идентификатор каждому символу:
- 0x41 → А
- 0xE1 → á
- 0x414 → Д
Итак, 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, - это присваивает каждому символу числовой идентификатор, называемый кодовой точкой, для простой и однозначной ссылки.
Кодировки
Сопоставьте символы с битовыми шаблонами.
Эти битовые комбинации используются для представления символов в памяти компьютера или на диске.
Существует множество различных кодировок, охватывающих разные подмножества символов. В англоязычном мире наиболее распространены следующие кодировки:
Преобразует 128 символов (кодовые точки U + 0000 в U + 007F) в битовые комбинации длиной 7.
Пример:
Вы можете увидеть все сопоставления в этой таблице .
Отображает 191 символ (кодовые точки от U + 0020 до U + 007E и от U + 00A0 до U + 00FF) в битовые комбинации длиной 8.
Пример:
- а → 01100001 (0x61)
- á → 11100001 (0xE1)
Вы можете увидеть все сопоставления в этой таблице .
Карты 1,112,064 символов (все существующее Unicode точки коды) битовые паттерны либо длина 8, 16, 24 или 32 бит (то есть, 1, 2, 3 или 4 байта).
Пример:
- а → 01100001 (0x61)
- á → 11000011 10100001 (0xC3 0xA1)
- ≠ → 11100010 10001001 10100000 (0xE2 0x89 0xA0)
- 😂 → 11110000 10011111 10011000 10000010 (0xF0 0x9F 0x98 0x82)
Кстати UTF-8 кодирует символы в битовые строки очень хорошо описано здесь .
Юникод и кодировки
Глядя на приведенные выше примеры, становится ясно, насколько полезен Unicode.
Например, если я Latin-1 и хочу объяснить свою кодировку á, мне не нужно говорить:
«Я кодирую это a с помощью aigu (или как вы называете эту восходящую полосу) как 11100001»
Но я могу просто сказать:
"Я кодирую U + 00E1 как 11100001"
И если я UTF-8 , я могу сказать:
«Я, в свою очередь, кодирую U + 00E1 как 11000011 10100001»
И всем однозначно ясно, о каком персонаже идет речь.
Теперь к часто возникающей путанице
Верно, что иногда битовый шаблон кодировки, если вы интерпретируете его как двоичное число, совпадает с кодовой точкой Unicode этого символа.
Например:
- ASCII кодирует a как 1100001, что можно интерпретировать как шестнадцатеричное число 0x61 , а кодовая точка Unicode a - U + 0061 .
- Latin-1 кодирует á как 11100001, что можно интерпретировать как шестнадцатеричное число 0xE1 , а кодовая точка Unicode для á - U + 00E1 .
Конечно, это сделано специально для удобства. Но вы должны смотреть на это как на чистое совпадение . Битовый шаблон, используемый для представления символа в памяти, никаким образом не привязан к кодовой точке Unicode этого символа.
Никто даже не говорит, что битовую строку типа 11100001 нужно интерпретировать как двоичное число. Просто посмотрите на это как на последовательность битов, которые Latin-1 использует для кодирования символа á .
Вернуться к вашему вопросу
Ваш интерпретатор Python использует кодировку UTF-8 .
Вот что происходит в ваших примерах:
Пример 1
Следующее кодирует символ á в UTF-8. В результате получается битовая строка 11000011 10100001, которая сохраняется в переменной a
.
>>> a = 'á'
Когда вы смотрите на значение a
, его содержимое 11000011 10100001 форматируется как шестнадцатеричное число 0xC3 0xA1 и выводится как '\xc3\xa1'
:
>>> a
'\xc3\xa1'
Пример 2
Следующее сохраняет кодовую точку Unicode для á, которая является U + 00E1, в переменной ua
(мы не знаем, какой формат данных Python использует внутри для представления кодовой точки U + 00E1 в памяти, и это неважно для нас):
>>> ua = u'á'
Когда вы смотрите на значение ua
, Python сообщает вам, что оно содержит кодовую точку U + 00E1:
>>> ua
u'\xe1'
Пример 3
Следующее кодирует кодовую точку Unicode U + 00E1 (представляющую символ á) с помощью UTF-8, что приводит к битовому шаблону 11000011 10100001. Опять же, для вывода этот битовый шаблон представлен как шестнадцатеричное число 0xC3 0xA1:
>>> ua.encode('utf-8')
'\xc3\xa1'
Пример 4
Следующее кодирует кодовую точку Unicode U + 00E1 (представляющую символ á) с помощью Latin-1, что приводит к битовому шаблону 11100001. Для вывода этот битовый шаблон представлен как шестнадцатеричное число 0xE1, которое по совпадению совпадает с исходным кодовая точка U + 00E1:
>>> ua.encode('latin1')
'\xe1'
Нет связи между объектом Unicode ua
и кодировкой Latin-1. То, что кодовая точка á - U + 00E1, а кодировка Latin-1 для á - 0xE1 (если вы интерпретируете битовый шаблон кодирования как двоичное число), является чистым совпадением.
unicode
, это просто абстракция символа Юникода;unicode
можно преобразовать вstr
некоторую кодировку (напримерutf-8
).