规范化复合/可分解/可变长度字符(unicode / python3.4)

时间:2015-04-27 21:03:29

标签: python python-3.x unicode python-unicode unicode-normalization

我偶然发现http://mortoray.com/2013/11/27/the-string-type-is-broken/

令我恐惧......

print(len('noe\u0308l')) # returns 5 not 4

然而我发现了 https://stackoverflow.com/a/14682498/1267259Normalizing Unicode

from unicodedata import normalize
print(len(unicodedata.normalize('NFC','noe\u0308l'))) # returns 4

但是我如何处理薛定谔的猫?

print(len('')) # returns 4 not 2

(旁边的问题:在我的文本编辑器中,当我试图保存时,我得到一个“utf-8编解码器无法编码位置y中的字符x:代理不允许”但在命令提示符下我可以粘贴并运行使用这些字符的代码,我认为这是因为猫存在于不同的量子级别(SMP),但我如何规范它们呢?)

我还有什么办法可以确保所有字符都算作“1”吗?

2 个答案:

答案 0 :(得分:2)

您的编辑器正在生成surrogate pairs,而不是实际的代码点,这就是您收到警告的原因。使用:

'\U0001f638\U0001f63e'

定义猫而不诉诸代理人。

如果你有一个带有代理项的字符串,你可以通过UTF-16重新编码这些字符串,并允许使用'surrogatepass'错误处理程序对代理进行编码:

>>> # \U0001f638 is \ud83d\ude38 when using UTF-16 surrogates
...
>>> '\ud83d\ude38'.encode('utf16', 'surrogatepass').decode('utf16')
''
>>> len(_)
1

来自Error Handlers documentation

  

'surrogateescape'
  在解码时,将字节替换为从U+DC80U+DCFF的单个代理代码。在编码数据时使用'surrogateescape'错误处理程序时,此代码将返回到相同的字节。 (有关详情,请参阅PEP 383。)

答案 1 :(得分:0)

对于任何版本的Python的一致代码点计数,编码为UTF-32并将字节数除以4.

print(len(unicodedata.normalize('NFC','noe\u0308l').encode('utf-32le')) / 4)
print(len('\U0001f638\U0001f63e'.encode('utf-32le')) / 4)