为什么字符串中的和音符去掉后变成了对应的ASCII字符?

python3-cookbook 中有一个这样的例子:

>>> import unicodedata
>>> import sys
>>> cmb_chrs = dict.fromkeys(c for c in range(sys.maxunicode)
...                         if unicodedata.combining(chr(c)))
>>> a = 'pýtĥöñ is awesome\n'
>>> b = unicodedata.normalize('NFD', a)
>>> b
'pýtĥöñ is awesome\n'
>>> b.translate(cmb_chrs)
'python is awesome\n'
>>>

cmb_chrs 每个键对应的值都是 None, 那么为什么在执行 b.translate(cmb_chrs) 后可以得到字符串 python is awesome\n ?

阅读 2.6k
2 个回答

如果你执行:

print([ord(x) for x in a])
# [112, 253, 116, 293, 246, 241, 32, 105, 115, 32, 97, 119, 101, 115, 111, 109, 101, 10]
print([ord(x) for x in b])
# [112, 121, 769, 116, 104, 770, 111, 776, 110, 771, 32, 105, 115, 32, 97, 119, 101, 115, 111, 109, 101, 10]

你会发现,虽然 ab 打印出来是一样的,内部的编码却不一样。原因在于 unicode.normalize 把带音调的字符都拆开了。而 cmb_chrs 中记录了音调符号的 Unicode 码,执行 b.translate 后,音调自然就没有了。

神奇的 unicode:

>>> list(a)
['p', 'ý', 't', 'ĥ', 'ö', 'ñ', ' ', 'i', 's', ' ', 'a', 'w', 'e', 's', 'o', 'm', 'e', '\n']
>>> list(b)
['p', 'y', '́', 't', 'h', '̂', 'o', '̈', 'n', '̃', ' ', 'i', 's', ' ', 'a', 'w', 'e', 's', 'o', 'm', 'e', '\n']
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题