我偶然发现http://mortoray.com/2013/11/27/the-string-type-is-broken/
令我恐惧......
print(len('noe\u0308l')) # returns 5 not 4
然而我发现了 https://stackoverflow.com/a/14682498/1267259, Normalizing 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”吗?
答案 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+DC80
到U+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)