На этом шаге мы рассмотрим некоторые возможности модуля unicodedata.
Вы работаете со строками Unicode и хотите убедиться, что все эти строки имеют одинаковое внутреннее представление.
В Unicode некоторые символы могут быть представлены несколькими допустимыми кодирующими последовательностями. Рассмотрим пример:
>>> s1 = 'Spicy Jalape\u00f1o' >>> s2 = 'Spicy Jalapen\u0303o' >>> s1 'Spicy Jalapeсño' >>> s2 'Spicy Jalapeсño' >>> s1 == s2 False >>> len(s1) 14 >>> len(s2) 15 >>>
Здесь текст "Spicy Jalapeño" представлен в двух формах. Первая использует полноценный символ "ñ" (U+00F1). Вторая использует латинскую букву "n", за которой следует дополняющий символ "~" (U+0303).
Такие множественные представления становятся проблемой для программ, которые занимаются сравнением строк. Чтобы это исправить, вы должны сначала нормализовать текст, то есть привести его к стандартному представлению с помощью модуля unicodedata:
>>> import unicodedata >>> t1 = unicodedata.normalize('NFC', s1) >>> t2 = unicodedata.normalize('NFC', s2) >>> t1 == t2 True >>> print(ascii(t1)) 'Spicy Jalape\xf1o' >>> >>> t3 = unicodedata.normalize('NFD', s1) >>> t4 = unicodedata.normalize('NFD', s2) >>> t3 == t4 True >>> print(ascii(t3)) 'Spicy Jalapen\u0303o' >>>
Первый аргумент, передаваемый в normalize(), определяет режим нормализации текста. NFC означает, что символы должны быть полноценными (то есть по возможности использовать только одну кодирующую последовательность). NFD означает, что символы должны быть декомпозированными, то есть разделенными на комбинирующиеся символы.
Python также поддерживает режимы нормализации NFKC и NFKD, которые добавляют возможности совместимости, позволяющие работать с определенными типами символов. Например:
>>> s = '\ufb01' # Один символ >>> s 'fi' >>> unicodedata.normalize('NFD', s) 'fi' >>> # Обратите внимание на разбивку объединенных букв >>> unicodedata.normalize('NFKD', s) 'fi' >>> unicodedata.normalize('NFKC', s) 'fi' >>>
Нормализация - это важная часть любой программы, в которой присутствует необходимость обработки текста в Unicode разумным и единообразным способом. Это особенно важно, когда обрабатываемые строки поступают из пользовательского ввода, кодировку которого вы практически никак не контролируете.
Нормализация также может быть важной частью чистки и фильтрации текста. Предположим, вы хотите удалить из текста диакритические знаки (возможно, для цели поиска совпадений):
>>> t1 = unicodedata.normalize('NFD', s1) >>> ''.join(c for c in t1 if not unicodedata.combining(c)) 'Spicy Jalapeno' >>>
Последний пример демонстрирует еще один важный аспект модуля unicodedata, а именно полезные функции для проверки принадлежности символов к определенным классам символов. Функция combining() проверяет, является ли символ объединяющимся. В этом модуле есть и другие функции для поиска символов определенных категорий, проверки цифр и т. д.
Unicode - весьма обширная тема. Для более подробной информации о нормализации посетите соответствующую страницу на сайте Unicode.
http://www.unicode.org/faq/normalization.html.
На следующем шаге мы рассмотрим использование символов Unicode в регулярных выражениях.