unicodedata.decomposition() 与 unicodedata.normalize(NFD/NFKD)?

unicodedata.decomposition() vs. unicodedata.normalize(NFD/NFKD)?

根据 py3 doc:

unicodedata.decomposition(chr)

Returns the character decomposition mapping assigned to the character chr as string. An empty string is returned in case no such mapping is defined.

这里不太明白字符分解映射是怎么定义的,[=14之间的relationship/difference是什么=] 和 unicodedata.normalize(NFD/NFKD)?.

参见以下示例:

$ python3
>>> import unicodedata
>>> unicodedata.decomposition('⑴')
'<compat> 0028 0031 0029'              <-- why not just '0028 0031 0029'?
>>> unicodedata.normalize('NFKD', '⑴')
'(1)'
>>> unicodedata.decomposition('①')
'<circle> 0031'                        <-- why not just '0031'?
>>> unicodedata.normalize('NFKD', '①')
'1'
>>> unicodedata.decomposition('è')
'0065 0300'                            <-- like this?
>>> unicodedata.normalize('NFD', 'è') == '\u0065\u0300'
True
>>>

映射是在 Unicode 标准中定义的。

K 是 "compatibility"。 Unicode 必须在 Unicode 中插入一些代码,以便能够进行往返而不丢失信息。 "K" 转换将删除此类 "extra/unwanted" 字符(根据其他规则,这些字符不应该在 Unicode 中)。

所以下标数字、上标数字、分数和圆圈数字(在你的例子中)被转换(它们应该是标准数字+标记格式(在 Unicode 之外,和字符)。

问题:使用下标,只能得到数字,所以要改变意思,例如 转化为 42。 K 会去掉一些文本的语义(本来就不应该有的,只是分解是不够的)

所以K不应该被使用,而是用于特定用途。其中一种用途是用于字符串搜索,或者查看一个用户名是否与其他用户名过于相似(可能无法区分)[但仅 'K' 是不够的。

D是归一化:D将字符分解为组件,因此ê被转化为e和组合字符^。这也是 Unicode 的目标之一:把所有的字符都编码成 65366 个编码是无法实现的,所以才组合了字符。 (这在汉字中最为明显)。同样,为了兼容性和往返,添加了一些重音字符,后来 Unicode 扩展到超过 65536 个代码。

所以我们有 D 代表分解的字符(基本 + 组合代码),C 有更紧凑的符号(如果有这样的组合)。这些转换也在 Unicode 标准中进行了描述(历史上的特殊情况很少,"bugs")。

unicodedata.decompositionreturns单个码位的分解类型和映射in the format used in the Unicode Character Database。来自 UAX #44:

Decomposition_Type, Decomposition_Mapping: This field contains both values, with the type in angle brackets.

如果尖括号中没有类型,则代码点具有用于 NFC 和 NFD 的 规范分解。如果尖括号中有类型,则代码点具有 兼容性分解 ,除了规范分解之外,NFKC 和 NFKD 还使用它。

unicodedata.normalize 对整个字符串实施 Unicode 规范化算法。