просто предостережение: использование list( '...' )
(в Py3; это u'...'
для Py2) не , в общем смысле, даст вам символов Unicode строка;скорее это скорее всего приведет к серии 16-битных кодовых точек.это верно для всех «узких» сборок CPython, на которые сегодня приходится подавляющее большинство установок Python.
, когда в 1990-х годах впервые был предложен юникод, было высказано предположение, что 16 бит будет более чем достаточно для покрытиявсе потребности универсального кодирования текста, поскольку он позволил перейти от 128 кодовых точек (7 бит) и 256 кодовых точек (8 бит) к колоссальным 65'536 кодовым точкам.однако вскоре стало очевидно, что это было желаемое за действительное;Сегодня в Unicode версии 5.2 определено около 100 000 кодовых точек, и еще тысячи ожидают включения.чтобы это стало возможным, юникод должен был перейти с 16 на (концептуально) 32 бита (хотя он не в полной мере использует 32-битное адресное пространство).
, чтобы поддерживать совместимость с программным обеспечением, созданнымисходя из предположения, что Юникод по-прежнему составляет 16 бит, были разработаны так называемые суррогатные пары, в которых две 16-битные кодовые точки из специально обозначенных блоков используются для выражения кодовых точек за пределами 65 536, то есть за пределами того, что Юникод называет «базовой многоязычной плоскостью».или BMP, и которые в шутку называют «астральными» плоскостями этого кодирования, из-за их относительной неуловимости и постоянной головной боли, которую они предлагают людям, работающим в области обработки и кодирования текста.
сейчас пока узкиеВ некоторых случаях CPython работает с суррогатными парами достаточно прозрачно, в других случаях он по-прежнему не может делать правильные вещи, а разделение строк является одним из наиболее проблемных случаев.в узкой сборке Python list( 'abc大?def' )
(или list( 'abc\u5927\U00027C3Cdef' )
при написании с escape-символами) приведет к ['a', 'b', 'c', '大', '\ud85f', '\udc3c', 'd', 'e', 'f']
, с '\ud85f', '\udc3c'
суррогатной парой.кстати, '\ud85f\udc3c'
- это то, что стандарт JSON ожидает от вас, чтобы представить U-27C3C
.любая из этих кодовых точек сама по себе бесполезна;правильно сформированная строка в юникоде может содержать только пары суррогатов.
, поэтому вы хотите разделить строку на символы на самом деле:
from re import compile as _Re
_unicode_chr_splitter = _Re( '(?s)((?:[\ud800-\udbff][\udc00-\udfff])|.)' ).split
def split_unicode_chrs( text ):
return [ chr for chr in _unicode_chr_splitter( text ) if chr ]
, которая корректно возвращает ['a', 'b', 'c', '大', '?', 'd', 'e', 'f']
(примечание: вы, вероятно, можете переписать регулярное выражение, так что фильтрация пустых строк становится ненужной).
, если все, что вы хотите сделать, это разделить текст на китайские символы, то на этом этапе вы почти закончили бы.не уверен, какова концепция «слова» в ОП, но для меня 这 是 一个 句子 может быть в равной степени разделена на 这 |是 |一 |个 |句子, а также 这 是 |一个 |句子, в зависимости от вашей точки зрения.однако все, что выходит за рамки понятия (возможно, составленных) символов и классов символов (символы против пробелов, букв и т. д.), выходит далеко за рамки того, что встроено в юникод и python;вам понадобится немного обработки естественного языка, чтобы сделать это.позвольте мне заметить, что хотя ваш пример 'yes the United Nations can!'.split()
успешно демонстрирует, что метод split делает что-то полезное для большого количества данных, он неправильно разбирает текст на английском языке на слова: он не распознает United Nations
как одно слово, в то время как онложно предполагает, что can!
- это слово, которым оно явно не является.этот метод дает как ложные срабатывания, так и ложные отрицания.в зависимости от ваших данных и того, что вы намереваетесь достичь, это может или не может быть тем, что вы хотите.