Юникод: необходимый практический минимум для каждого разработчика / Хабр

Основные принципы юникода

Все мы прекрасно понимаем, что компьютер ни о каких идеальных сущностях знать не знает, а оперирует битами и байтами. Но компьютерные системы пока создают люди, а не машины, и для нас с вами иногда бывает удобнее оперировать умозрительными концепциями, а затем уже переходить от абстрактного к конкретному.

Важно! Одним из центральных принципов в философии Юникода является чёткое разграничение между символами, их представлением в компьютере и их отображением на устройстве вывода.

Вводится понятие абстрактного юникод-символа, существующего исключительно в виде умозрительной концепции и договорённости между людьми, закреплённой стандартом. Каждому юникод-символу поставлено в соответствие неотрицательное целое число, именуемое его кодовой позицией (code point).

Так, например, юникод-символ U 041F — это заглавная кириллическая буква П. Существует несколько возможностей представления данного символа в памяти компьютера, ровно как и несколько тысяч способов отображения его на экране монитора. Но при этом П, оно и в Африке будет П или U 041F.

Это хорошо нам знакомая инкапсуляция или отделение интерфейса от реализации — концепция, отлично зарекомендовавшая себя в программировании.

Получается, что руководствуясь стандартом, любой текст можно закодировать в виде последовательности юникод-символов

Привет
U 041F U 0440 U 0438 U 0432 U 0435 U 0442

записать на листочке, упаковать в конверт и переслать в любой конец Земли. Если там знают о существовании Юникода, то текст будет воспринят ими ровно так же, как и нами с вами. У них не будет ни малейших сомнений, что предпоследний символ — это именно кириллическая строчная

е

(U 0435), а не скажем латинская маленькая

e

(U 0065). Обратите внимание, что мы ни слова не сказали о байтовом представлении.

Хотя юникод-символы и называются символами, они далеко не всегда соответствуют символу в традиционно-наивном понимании, например букве, цифре, пунктуационному знаку или иероглифу. (Подробнее смотри под спойлером.)

Примеры различных юникод-символов

Существуют чисто технические юникод-символы, например:

  • U 0000: нулевой символ;
  • U D800–U DFFF: младшие и старшие суррогаты для технического представления кодовых позиций в диапазоне от 10000 до 10FFFF (читай: за пределами БМЯП/BMP) в семействе кодировок UTF-16;
  • и т.д.

Существуют пунктуационные маркеры, например U 200F: маркер смены направления письма справа-налево.

Существует целая когорта пробелов различной ширины и назначения (см. отличную хабра-статью: всё (или почти всё) о пробеле):

  • U 0020 (пробел);
  • U 00A0 (неразрывный пробел,   в HTML);
  • U 2002 (полукруглая шпация или En Space);
  • U 2003 (круглая шпация или Em Space);
  • и т.д.

Существуют комбинируемые диакритические знаки (сombining diacritical marks) — всевозможные штрихи, точки, тильды и т.д., которые меняют/уточняют значение предыдущего знака и его начертание. Например:

  • U 0300 и U 0301: знаки основного (острого) и второстепенного (слабого) ударений;
  • U 0306: кратка (надстрочная дуга), как в й;
  • U 0303: надстрочная тильда;
  • и т.д.

Существует даже такая экзотика, как языковые тэги (U E0001, U E0020–U E007E, и U E007F), которые сейчас находятся в подвешенном состоянии. Они задумывались как возможность маркировать определённые участки текста как относящиеся к тому или иному варианту языку (скажем американский и британский вариант английского), что могло влиять на детали отображения текста.

Что такое символ, чем отличается графемный кластер (читай: воспринимаемое как единое целое изображение символа) от юникод-символа и от кодового кванта мы расскажем в следующий раз.

Хочу ещё!

Хорошо, используем бабу-ягу из примера выше ещё раз:

>>> parser_result = u'баба-яга'   #1
>>> parser_result
u'xe1xe0xe1xe0-xffxe3xe0'   #2
>>> print parser_result
áàáà-ÿãà   #3
>>> print parser_result.encode('latin1')  #4
баба-яга
>>> print parser_result.encode('latin1').decode('cp1251')  #5
баба-яга
>>> print unicode('баба-яга', 'cp1251')   #6
баба-яга

Пример не совсем простой, но тут есть всё (ну или почти всё). Что здесь происходит:

  1. Что имеем на входе? Байты, которые IDLE передает интерпретатору. Что нужно на выходе? Юникод, то есть символы. Осталось байты превратить в символы — но ведь надо кодировку, правда? Какая кодировка будет использована? Смотрим дальше.
  2. Здесь важной момент:
    >>> 'баба-яга'
    'xe1xe0xe1xe0-xffxe3xe0'
    >>> u'u00e1u00e0u00e1u00e0-u00ffu00e3u00e0' == u'xe1xe0xe1xe0-xffxe3xe0'
    True
    

    как видим, Пайтон не заморачивается с выбором кодировки — байты просто превращаются в юникод-поинты:

    >>> ord('а')
    224
    >>> ord(u'а')
    224
    
  3. Только вот проблема — 224-ый символ в cp1251 (кодировка, которая используется интерпретатором) совсем не тот, что 224 в Юникоде. Именно из-за этого получаем кракозябры при попытке напечатать нашу юникод-строку.
  4. Как помочь бабе? Оказывается, что первые 256 символов Юникода те же, что и в кодировке ISO-8859-1latin1, соответственно, если используем её для кодировки юникод-строки, получим те байты, которые вводили сами (кому интересно — Objects/unicodeobject.c, ищем определение функции «unicode_encode_ucs1»):
    >>> parser_result.encode('latin1')
    'xe1xe0xe1xe0-xffxe3xe0'
    
  5. Как же получить бабу в юникоде? Надо указать, какую кодировку использовать:
    >>> parser_result.encode('latin1').decode('cp1251')
    u'u0431u0430u0431u0430-u044fu0433u0430'
    
  6. Способ с пункта #5 конечно не ахти, намного удобней использовать использовать built-in unicode.

На самом деле не всё так плохо с «u”» литералами, поскольку проблема возникает только в консоле. Ведь в случае использования non-ascii символов в исходном файле Пайтон будет настаивать на использовании заголовка типа “# -*- coding: -*-” (

), и юникод-строки будут использовать правильную кодировку.

Есть ещё способ использования «u”» для представления, например, кириллицы, и при этом не указывать кодировку или нечитабельные юникод-поинты (то есть «u’u1234’»). Способ не совсем удобный, но интересный — использовать unicode entity codes:

>>> s = u'N{CYRILLIC SMALL LETTER KA}N{CYRILLIC SMALL LETTER O}N{CYRILLIC SMALL LETTER SHCHA}N{CYRILLIC SMALL LETTER IE}N{CYRILLIC SMALL LETTER SHORT I}'
>>> print s
кощей

Ну и вроде всё. Основные советы — не путать «encode»«decode» и понимать различия между байтами и символами.

Не кодируется 🙁

Разберем примеры с начала статьи. Как работает конкатенация строки и юникод-строки? Простая строка должна быть превращена в юникод-строку, и поскольку интерпретатор не знает кодировки, от использует кодировку по умолчанию — ascii. Если этой кодировке не удастся декодировать строку, получим некрасивую ошибку. В таком случае нам нужно самим привести строку к юникод-строке, используя правильную кодировку:

>>> print type(parser_result), parser_result
<type 'unicode'> баба-яга
>>> s = 'кощей'
>>> parser_result   s
Traceback (most recent call last):
  File "<pyshell#67>", line 1, in <module>
    parser_result   s
UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 0: ordinal not in range(128)
>>> parser_result   s.decode('cp1251')
u'xe1xe0xe1xe0-xffxe3xe0u043au043eu0449u0435u0439'
>>> print parser_result   s.decode('cp1251')
баба-ягакощей
>>> print '&'.join((parser_result, s.decode('cp1251')))
баба-яга&кощей   # Так лучше :)

«UnicodeDecodeError» обычно есть свидетельством того, что нужно декодировать строку в юникод, используя правильную кодировку.

Теперь использование «str» и юникод-строк. Не используйте «str» и юникод строки 🙂 В «str» нет возможности указать кодировку, соответственно кодировка по умолчанию будет использоваться всегда и любые символы > 128 будут приводить к ошибке. Используйте метод «encode»:

>>> print type(s), s
<type 'unicode'> кощей
>>> str(s)
Traceback (most recent call last):
  File "<pyshell#90>", line 1, in <module>
    str(s)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)
>>> s = s.encode('cp1251')
>>> print type(s), s
<type 'str'> кощей

«UnicodeEncodeError» — знак того, что нам нужно указать правильную кодировку во время превращения юникод-строки в обычную (или использовать второй параметр ‘ignore”replace”xmlcharrefreplace’ в методе «encode»).

Сейчас ищут техподдержку:  Официальный сайт Сбербанка России

Кодировки


Если мы хотим переслать текст через Интернет, то нам потребуется закодировать последовательность юникод-символов в виде последовательности байтов.

Стандарт Юникода включает в себя описание ряда юникод-кодировок, например UTF-8 и UTF-16BE/UTF-16LE, которые позволяют кодировать всё пространство кодовых позиций. Конвертация между этими кодировками может свободно осуществляться без потерь информации.

Также никто не отменял однобайтные кодировки, но они позволяют закодировать свой индивидуальный и очень узкий кусочек юникод-спектра — 256 или менее кодовых позиций. Для таких кодировок существуют и доступны всем желающим таблицы, где каждому значению единственного байта сопоставлен юникод-символ (см. например CP1251.TXT).

Из юникод-кодировок самой распространённой в Интернете является UTF-8 (она завоевала пальму первенства в 2008 году), главным образом благодаря её экономичности и прозрачной совместимости с семибитной ASCII. Латинские и служебные символы, основные знаки препинания и цифры — т.е. все символы семибитной ASCII — кодируются в UTF-8 одним байтом, тем же, что и в ASCII.

Обратите внимание, что UTF-8 — это кодировка с переменной длиной кода. Каждый юникод-символ в ней представляется последовательностью кодовых квантов с минимальной длиной в один квант. Число 8 означает битовую длину кодового кванта (code unit) — 8 бит. Для семейства кодировок UTF-16 размер кодового кванта составляет, соответственно, 16 бит. Для UTF-32 — 32 бита.

Так появился unicode

Unicode расшифровывают как

(UCS), и у него есть официальное обозначение ISO/IEC 10646. Но обычно все используют название Unicode.

Этот стандарт помог решить проблемы, возникавшие из-за кодировки и кодовых страниц. Он содержит множество кодовых пунктов (кодовых точек), присвоенных символам из языков и культур со всего мира. То есть Unicode — это набор символов.

Кто-то проделал огромную работу, сопоставляя каждый символ во всех языках с уникальными кодами. Вот как это выглядит:

«Hello World»

U 0048 : латинская прописная H
U 0065 : латинская строчная E
U 006C : латинская строчная L
U 006C : латинская строчная L
U 006F : латинская строчная O
U 0020 : пробел
U 0057 : латинская прописная W
U 006F : латинская строчная O
U 0072 : латинская строчная R
U 006C : латинская строчная L
U 0064 : латинская строчная D

Префикс U говорит о том, что это стандарт Unicode, а число — это результат преобразования двоичных чисел. Стандарт использует шестнадцатеричную нотацию, которая является упрощённым представлением двоичных чисел.

вы можете ввести в поле что угодно и посмотреть, как это будет преобразовано в Unicode. А

можно полюбоваться на все 143 859 кодовых пунктов.

Уточню на всякий случай: речь идёт о большом словаре кодовых пунктов, присвоенных всевозможным символам. Это очень большой набор символов, не более того.

Осталось добавить последний ингредиент.

Зачем понадобился юникод?

До появления Юникода, почти повсеместно использовались однобайтные кодировки, в которых граница между самими символами, их представлением в памяти компьютера и отображением на экране была довольно условной. Если вы работали с тем или иным национальным языком, то в вашей системе были установлены соответствующие шрифты-кодировки, которые позволяли отрисовывать байты с диска на экране таким образом, чтобы они представляли смысл для пользователя.

Если вы распечатывали на принтере текстовый файл и на бумажной странице видели набор непонятных кракозябр, это означало, что в печатающее устройство не загружены соответствующие шрифты и оно интерпретирует байты не так, как вам бы этого хотелось.

У такого подхода в целом и однобайтовых кодировок в частности был ряд существенных недостатков:

  1. Можно было одновременно работать лишь с 256 символами, причём первые 128 были зарезервированы под латинские и управляющие символы, а во второй половине кроме символов национального алфавита нужно было найти место для символов псевдографики (╔ ╗).
  2. Шрифты были привязаны к конкретной кодировке.
  3. Каждая кодировка представляла свой набор символов и конвертация из одной в другую была возможна только с частичными потерями, когда отсутствующие символы заменялись на графически похожие.
  4. Перенос файлов между устройствами под управлением разных операционных систем был затруднителен. Нужно было либо иметь программу-конвертер, либо таскать вместе с файлом дополнительные шрифты. Существование Интернета каким мы его знаем было невозможным.
  5. В мире существуют неалфавитные системы письма (иероглифическая письменность), которые в однобайтной кодировке непредставимы в принципе.

Зачем нам новый тип «unicode»?

Вот мы и добрались до самого интересного. Что такое строка в Python 2.x? Это просто

байты

. Просто бинарные данные, которые могут быть чем-угодно. На самом деле, когда мы пишем что-нибудь вроде:

>>> x = 'abcd'
>>> x
'abcd'

интерпретатор не создает переменную, которая содержит первые четыре буквы латинского алфавита, но только последовательность

('a', 'b', 'c', 'd')

с четырёх байт, и латинские буквы здесь используются исключительно для обозначения именно этого значения байта. То есть ‘a’ здесь просто синоним для написания ‘x61’, и ни чуточку больше. Например:

>>> 'x61' 
'a'
>>> struct.unpack('>4b', x)  # 'x' - это просто четыре signed/unsigned char-а
(97, 98, 99, 100)
>>> struct.unpack('>2h', x)  # или два short-а
(24930, 25444)
>>> struct.unpack('>l', x)  # или один long
(1633837924,)
>>> struct.unpack('>f', x)  # или float
(2.6100787562286154e 20,)
>>> struct.unpack('>d', x * 2)   # ну или половинка double-а
(1.2926117739473244e 161,)


И всё!

И ответ на вопрос — зачем нам «unicode» уже более очевиден — нужен тип, который будет представятся символами, а не байтами.

Именованные символьные ссылки

В начале было слово..  (с)

А в нашем случае был метаязык SGML (Standard Generalized Markup Language), на котором определялись языки разметки документов. HTML до версии 4 включительно был приложением SGML, а XML является подмножеством SGML.

В частности, SGML помимо декларативной разметки и описания типов документов (document type definition, DTD), обладал механизмом строковой подстановки, когда некоторая последовательность символов заменяется при обработке некоторой другой последовательностью (для обеспечения переносимости нестандартных символов).

В SGML строки, для которых определены подстановки, назывались entities (иногда их переводят как “объекты”, Википедия называет их “символ-мнемоника”). После того, как entities объявлен, на него можно ссылаться в любом месте документа, используя его имя, перед которым ставится символ “&”, а после которого – точка с запятой. Точка с запятой может быть опущена, если за ссылкой на entities следует пробел или конец записи.

Сейчас ищут техподдержку:  Подать жалобу в налоговые органы | ФНС России | 77 город Москва

В HTML определено много entities для специальных символов, вроде валют и математических знаков, а также для отображения символов, имеющих специальное значение для HTML (например, < и >). Их описание можно найти на официальном сайте консорциума.

Затем символ можно использовать в документе:

Такое описание выглядит нагляднее, но по факту просто заменяется на:

В сухом остатке

Информации много и имеет смысл привести краткую выжимку всего, что было написано выше:

  • Юникод постулирует чёткое разграничение между символами, их представлением в компьютере и их отображением на устройстве вывода.
  • Юникод-символы не всегда соответствуют символу в традиционно-наивном понимании, например букве, цифре, пунктуационному знаку или иероглифу.
  • Кодовое пространство Юникода состоит из 1 114 112 кодовых позиций в диапазоне от 0 до 10FFFF.
  • Базовая многоязыковая плоскость включает в себя юникод-символы от U 0000 до U FFFF, которые кодируются в UTF-16 двумя байтами.
  • Любая юникод-кодировка позволяет закодировать всё пространство кодовых позиций Юникода и конвертация между различными такими кодировками осуществляется без потерь информации.
  • Однобайтные кодировки позволяют закодировать лишь небольшую часть юникод-спектра, но могут оказаться полезными при работе с большим объёмом моноязыковой информации.
  • Кодировки UTF-8 и UTF-16 обладают переменной длиной кода. В UTF-8 каждый юникод-символ может быть закодирован одним, двумя, тремя или четырьмя байтами. В UTF-16 — двумя или четырьмя байтами.
  • Внутренний формат хранения текстовой информации в рамках отдельного приложения может быть произвольным при условии корректной работы со всем пространством кодовых позиций Юникода и отсутствии потерь при трансграничной передаче данных.

Ближе к делу!

Естественно, есть поддержка Юникода и в Пайтоне. Но, к сожалению, только в Python 3 все строки стали юникодом, и новичкам приходиться убиваться об ошибки типа:

>>> with open('1.txt') as fh:
	s = fh.read()

>>> print s
кощей
>>> parser_result = u'баба-яга'  # присвоение для наглядности, представим себе, что это результат работы какого-то парсера
>>> parser_result   s
Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    parser_result   s
UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 0: ordinal not in range(128)

или так:

>>> str(parser_result)
Traceback (most recent call last):
  File "<pyshell#52>", line 1, in <module>
    str(parser_result)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)


Давайте разберемся, но по порядку.

Css unicode не работает

Когда я изменяю unicode любого из приведенного ниже кода, он не работает, и я не знаю почему. кажется, что он работает только с такими стандартными, которые я копировал из Интернета.

 .demo-wrapper .panel.left a:before {
content: '';
display: inline-block;
position: absolute;
width: 24px;
height: 24px;
top: 15px;
left: 20px;
font-family: 'hk-demo';
text-align: center;
font-size: 18px;
}
.demo-wrapper .panel.left .newsfeed a:before {
content: 'f09e';
}
.demo-wrapper .panel.left .profile a:before {
content: '👤';
}

.demo-wrapper .panel.left .setting a:before {
content: '2699';
}
.demo-wrapper .panel.left .logout a:before {
content: 'e78e';
}
.demo-wrapper .panel.left .report a:before {
content: 'f0e0';
}

например, когда я меняю f09e ‘наf03e, это не сработает. Я пробовал несколько кодов Юникода, это не работает, пока я не использую по умолчанию, которые я получил из Интернета

.может кто-то, пожалуйста, разрешите это для меня

Краткое замечание про кодирование

С термином кодирование может произойти некоторая путаница. В рамках Юникода кодирование происходит дважды. Первый раз кодируется набор символов Юникода (character set), в том смысле, что каждому юникод-символу ставится с соответствие кодовая позиция.

В англоязычной терминологии существуют два разных глагола to code и to encode, но даже носители языка зачастую в них путаются. К тому же термин набор символов (character set или charset) используется в качестве синонима к термину кодированный набор символов (coded character set).

Всё это мы говорим к тому, что имеет смысл обращать внимание на контекст и различать ситуации, когда речь идёт о кодовой позиции абстрактного юникод-символа и когда речь идёт о его байтовом представлении.

Как пользоваться юникодом?

Юникод-строку в Python 2.6 можно создать тремя (как минимум, естественно) способами:

ascii в последних двух примерах указывается в качестве кодировки, что будет использоваться для превращения байтов в символы. Этапы этого превращения выглядят примерно так:

'x61' -> кодировка ascii -> строчная латинская "a" -> u'u0061' (unicode-point для этой буквы)

или

'xe0' -> кодировка c1251 -> строчная кириличная "a" -> u'u0430'

Как из юникод-строки получить обычную? Закодировать её:

>>> u'abc'.encode('ascii')
'abc'

Алгоритм кодирования естественно обратный приведенному выше.

Запоминаем и не путаем — юникод == символы, строка == байты, и байты -> что-то значащее (символы) — это де-кодирование (decode), а символы -> байты — кодирование (encode).

Кодовое пространство юникода

Кодовое пространство Юникода состоит из 1 114 112 кодовых позиций в диапазоне от 0 до 10FFFF. Из них к девятой версии стандарта значения присвоены лишь 128 237. Часть пространства зарезервирована для частного использования и консорциум Юникода обещает никогда не присваивать значения позициям из этих специальный областей.

Ради удобства всё пространство поделено на 17 плоскостей (сейчас задействовано шесть их них). До недавнего времени было принято говорить, что скорее всего вам придётся столкнуться только с базовой многоязыковой плоскостью (Basic Multilingual Plane, BMP), включающей в себя юникод-символы от U 0000 до U FFFF.

(Забегая немного вперёд: символы из BMP представляются в UTF-16 двумя байтами, а не четырьмя). В 2021 году этот тезис уже вызывает сомнения. Так, например, популярные символы Эмодзи вполне могут встретиться в пользовательском сообщении и нужно уметь их корректно обрабатывать.

Напоследок про utf

Коды являются

ключами

Как нам задавать кодировку? Поскольку HTML пишется на английском, и почти все кодировки прекрасно работают с английским, мы можем указать кодировку в начале раздела <hеad>.


Важно сделать это в самом начале

, поскольку парсинг

, если в данный момент используется неправильная кодировка. Также узнать версию кодировки можно из заголовка

Проблемы с ascii


Позиции со 128 по 255 были пустыми. Общественность задумалась, чем их заполнить.

Но у всех были разные идеи

. Американский национальный институт стандартов (American National Standards Institute, ANSI) формулирует стандарты для разных отраслей. Там утвердили позиции ASCII с 0 по 127. Их никто не оспаривал. Проблема была с остальными позициями.

Вот чем были заполнены позиции 128-255 в первых компьютерах IBM:

Какие-то загогулины, фоновые иконки, математические операторы и символы с диакретическим знаком вроде é. Но разработчики других компьютерных архитектур не поддержали инициативу. Всем хотелось внедрить свою собственную кодировку во второй половине ASCII.

Сейчас ищут техподдержку:  Frendex: закрытый элитклуб или очередной развод на финансовом рынке?

Все эти различные концовки назвали кодовыми страницами.

Что такое кодовые страницы ascii?

собрана коллекция из более чем 465 разных кодовых страниц! Существовали разные страницы даже в рамках какого-то одного языка, например, для греческого и китайского. Как можно было стандартизировать этот бардак? Или хотя бы заставить его работать между разными языками?

Эта проблема даже получила название Mojibake (бнопня, кракозябры). Так говорят про искажённый текст, который получается при использовании некорректной кодировки. В переводе с японского mojibake означает «преобразование символов».

Пример бнопни (кракозябров).

Безумие какое-то…

Именно! Не было ни единого шанса надёжно преобразовывать данные. Интернет — это лишь монструозное соединение компьютеров по всему миру. Представьте, что все страны решили использовать собственные стандарты. Например, греческие компьютеры принимают только греческий язык, а английские отправляют только английский. Это как кричать в пустой пещере, тебя никто не услышит.

ASCII уже не удовлетворял жизненным требованиям. Для всемирного интернета нужно было создать что-то другое, либо пришлось бы иметь дело с сотнями кодовых страниц.

��� Если только ������ вы не хотели ��� бы ��� читать подобные параграфы. �֎֏0590֐��׀ׁׂ׃ׅׄ׆ׇ

Заключение

При написании этой статьи я узнал о

. С 1993 года он предложил больше 200 изменений в Unicode, добавил в стандарт тысячи символов. По состоянию на 2003 год он считался самым продуктивным участником. Он один очень сильно повлиял на облик Unicode. Майкл — один из тех, кто сделал интернет таким, каким мы его сегодня знаем. Очень впечатляет.

Надеюсь, мне удалось показать вам, для чего нужны кодировки, какие проблемы они решают, и что происходит при их сбоях.

В заключение

В Юникоде так много различных аспектов, что осветить всё в рамках одной статьи невозможно. Да и ненужно. Приведённой выше информации вполне достаточно, чтобы не путаться в основных принципах и работать с текстом в большинстве повседневных задач (читай: не выходя за рамки BMP).

Зачем кто-то использует юникод?

Почему мой любимый html-парсер возвращает Юникод? Пусть возвращает обычную строку, а я там уже с ней разберусь! Верно? Не совсем. Хотя каждый из существующих в Юникоде символов и можно (наверное) представить в некоторой однобайтовой кодировке (ISO-8859-1, cp1251 и другие называют однобайтовыми, поскольку любой символ они кодируют ровно в один байт), но что делать если в строке должны быть символы с разных кодировок? Присваивать отдельную кодировку каждому символу? Нет, конечно, надо использовать Юникод.

Зачем?

Главный вопрос новичка, который встречается с впечатляющим количеством кодировок и на первый взгляд запутанными механизмами работы с ними (например, в Python 2.x). Краткий ответ — потому что так сложилось 🙂

Кодировкой, кто не знает, называют способ представления в памяти компьютера (читай — в нулях-единицахчислах) цифр, буков и всех остальных знаков. Например, пробел представляется как 0b100000 (в двоичной), 32 (в десятичной) или 0x20 (в шестнадцатеричной системе счисления).

Хорошо, я понял чем есть строка. тогда что такое юникод в пайтоне?

«type unicode» — это прежде всего абстракция, которая реализует идею Юникода (набор символов и связанных с ними чисел). Объект типа «unicode» — это уже не последовательность байт, но последовательность собственно символов без какого либо представления о том, как эти символы эффективно сохранить в памяти компьютера.

Введение в кодировку

Компьютеры понимают лишь двоичные числа — нули и единицы, это их язык. Больше ничего. Одно число называется байтом, каждый байт состоит из восьми битов. То есть восемь нулей и единиц составляют один байт. Внутри компьютеров всё сводится к двоичности — языки программирования, движений мыши, нажатия клавиш и все слова на экране.

Ссылки

  1. Character entity references in HTML 4 (in HTML 5)
  2. Character references in HTML 4 (in HTML 5)
  3. Using character escapes in markup and CSS

Не отображаются символы юникод

«Квадраты» у Вас отображаются потому, что шрифт, используемый в программе, не знает как отобразить тот или иной символ из unicode. Решить этот вопрос можно либо нахождением такого шрифта, который есть на всех машинах, на которые программа может быть установлена(сложно), либо же распространять шрифт с программой, предварительно узнав, можно ли так делать с точки зрения лицензионного соглашения, ассоциированного со шрифтом.

Шестнадцатеричные символьные ссылки

Аналогично десятичному представлению можно использовать шестнадцатеричное, добавим большую или малую латинскую “x” (икс) перед шестнадцатеричным кодом символа.

Через числовые ссылки можно сослаться на любой символ таблицы Unicode, за исключением символов с кодами U 0000 и U 000D, перманентно не определённых символов, суррогатов (U D800–U DFFF) и управляющих символов помимо пробельных.

Десятичные символьные ссылки

Возьмём произвольный символ Unicode, например, тильду (~). Её можно ввести с клавиатуры, но мы попробуем сделать это с помощью десятичной ссылки.

Код символа в таблице: U 007E.Переводим в десятичный формат: 7E16 = 7*16 14 = 12610Чтобы отобразить символ в HTML документе, нужно поместить его код между “&#” и “;”.

Unicode и html

В HTML есть несколько способов включить символ в текст документа. Помимо непосредственного ввода символа можно использовать ссылки (character references). Ссылки могут быть десятичными, шестнадцатеричными или именованными.

Это всё?

Unicode ещё не завершён. Как и в случае с любым стандартом, мы что-то добавляем, убираем, предлагаем новое. Никакие спецификации нельзя назвать «завершёнными». Обычно в год бывает 1-2 релиза, найти их описание можно

Python 3

Здесь без кода, ибо опыта нет. Свидетели утверждают, что там всё значительно проще и веселее. Кто возьмется на кошках продемонстрировать различия между здесь (Python 2.x) и там (Python 3.x) — респект и уважуха.

Полезно

Раз уж мы о кодировках, порекомендую ресурс, который время-от-времени помогает побороть кракозябры —

Unicode и css

В CSS тоже можно обращаться к символам через их коды, но формат записи отличается от HTML. Код символа предваряется обратным слешем ().

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

Оставьте комментарий

Adblock
detector