2017-01-22 11 views
4

Я немного смущен тем, как Python 3 обрабатывает многобайтовые символы юникода. Вот пример с смайликом:Выбор подстроки с использованием многобайтовых символов Unicode в Python 3

In [1]: print('☺️') 
☺️ 

In [2]: print(len('☺️')) 
2 

In [3]: print('☺️'[0]) 
☺ 

In [4]: print('☺️'[1]) 
️ 

In [5]: print(len('‍')) 
4 

Поскольку я работаю на небольшое хобби проекта по смайликам, это вызывает определенные проблемы для меня, так как я предпочел бы иметь дело с смайликами в виде отдельных строк символов, а не лечение как многоканальные строки, как это делает Python 3. Почему Python 3 не признает это как один символ, и как мне работать и работать с emojis таким образом, который я бы предпочел?

Если это довольно проблема с моим терминалом или REPL, я использую терминал macOS Sierra с iPython 5.1.0.

+0

☺️ представлен * двумя * байтами с использованием схемы UTF-16. – Maroun

+0

@MarounMaroun Конечно, но это все равно один символ? UTF- (8 | 16) поддерживает многобайтовые символы. –

+0

@MarounMaroun Это четыре байта в UTF-16. –

ответ

3

Проблема заключается в том, что ваши обе строки ('☺️' и '') содержат один невидимый характер каждого:

>>> '☺️'[0] 
'☺' 
>>> '☺️'[1] 
'️' 
>>> '☺️'[1].encode('unicode_escape') 
b'\\ufe0f'        # !!!!!!!!!! 
>>> '‍'[0] 
'' 
>>> '‍'[1] 
'' 
>>> '‍'[2] 
'\u200d'        # !!!!!!!!!! 
>>> '‍'[3] 
'' 

Персонаж '\ufe0f' (U + FE0F) является Variation Selector-16, что элемент кода

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

Персонаж '\u200d' (U + 200D) является Zero Width Joiner.

+0

Это интересно, поэтому Python 3 на самом деле не справляется с emojis правильно с точки зрения юникода; emoji действительно мультисимвольный символ? Похоже, мне нужно создать подкласс класса String, который будет искать случаи краев emoji ...? –

+0

Персонажи, и особенно emoji, могут состоять из произвольного количества кодовых точек. Техническим термином для такой группы является кластер графем *. [Несколько примеров здесь.] (Http://stackoverflow.com/documentation/unicode/6485/characters-can-consist-of-multiple-code-points#t=201701222129426089213). Я думаю, что есть несколько вопросов о SO о том, как для итерации над этими графемными кластерами. – roeland

+0

Модуль сторонних разработчиков 'regex' имеет' \ X' для соответствия кластерам графемы. –