2.9 经常会遇到字符串的Unicode编码,我们需要确保所有的字符串都拥有相同的底层表示。
- 在Unicode中有些特定的字符可以表示成多种合法的代码点序列,为了说明这个问题,代码示例如下
>>> s1 ='Spicy Jalape\u00f1o'
>>> s2 ='Spicy Jalapen\u0303o'
>>> s1
'Spicy Jalapeño'
>>> s2
'Spicy Jalapeño'
>>> s1==s2
False
>>> len(s1)
14
>>> len(s2)
15
>>>
-
‘Spicy Jalapeño’ 字符串用两种形式表达了出来,第一种使用的是字符’ñ’的全组成形式(fully composed) (U+00F1)第二种使用的是拉丁字母n后边尽更一个~组合而成的字符(U+0303)
-
对于一个比较字符串的程序来说,用一个文本拥有多种不同的表示形式是个大问题。
-
我们应该将文本同一表示为规范形式,这可以通过unicodedata模块来完成。
>>> import unicodedata
>>> t1 = unicodedata.normalize('NFC',s1)
>>> t2 = unicodedata.normalize('NFC',s2)
>>> t1 == t2
True
>>> print(ascii(t1))
'Spicy Jalape\xf1o'
>>> t3= unicodedata.normalize('NFD',s1)
>>> t4= unicodedata.normalize('NFD',s2)
>>> t3 == t4
True
>>> print(ascii(t3))
'Spicy Jalapen\u0303o'
>>>
- normalize() 的第一个参数制定了字符串该如何完成规范表示,NFC表示字符串应该是全组成的(即如果可能的话就使用单个代码点)。NFD表示应该使用组合字符,每个字符应该是能完全分开的。
- python支持NFKC和NFKD的凡是表达式形式,他们为处理特定类型的字符增加了额外的兼容功能。例如:
>>> s = '\ufb01'
>>> s
'fi'
>>> unicodedata.normalize('NFD',s)
'fi'
>>> unicodedata.normalize('NFKD',s)
'fi'
>>> unicodedata.normalize('NFKC',s)
'fi'
>>>
- 我们无法控制用户输入的字符串编码格式,所以标准的编码规范尤为重要