2.9 å°†Unicodeæ–‡æœ¬æ ‡å‡†åŒ–Â¶
问题¶
ä½ æ£åœ¨å¤„ç�†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â€�使用了两ç§�å½¢å¼�æ�¥è¡¨ç¤ºã€‚ 第一ç§�使用整体å—符â€�ñâ€�(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' # A single character
>>> s
'�'
>>> unicodedata.normalize('NFD', s)
'�'
# Notice how the combined letters are broken apart here
>>> unicodedata.normalize('NFKD', s)
'fi'
>>> unicodedata.normalize('NFKC', s)
'fi'
>>>
讨论¶
æ ‡å‡†åŒ–å¯¹äºŽä»»ä½•éœ€è¦�以一致的方å¼�处ç�†Unicode文本的程åº�都是é�žå¸¸é‡�è¦�的。 当处ç�†æ�¥è‡ªç”¨æˆ·è¾“入的å—ç¬¦ä¸²è€Œä½ å¾ˆéš¾åŽ»æŽ§åˆ¶ç¼–ç �的时候尤其如æ¤ã€‚
在清ç�†å’Œè¿‡æ»¤æ–‡æœ¬çš„æ—¶å€™å—ç¬¦çš„æ ‡å‡†åŒ–ä¹Ÿæ˜¯å¾ˆé‡�è¦�的。 比如,å�‡è®¾ä½ 想清除掉一些文本上é�¢çš„å�˜éŸ³ç¬¦çš„æ—¶å€™(å�¯èƒ½æ˜¯ä¸ºäº†æ�œç´¢å’ŒåŒ¹é…�):
>>> t1 = unicodedata.normalize('NFD', s1)
>>> ''.join(c for c in t1 if not unicodedata.combining(c))
'Spicy Jalapeno'
>>>
最å�Žä¸€ä¸ªä¾‹å�展示了 unicodedata 模å�—çš„å�¦ä¸€ä¸ªé‡�è¦�æ–¹é�¢ï¼Œä¹Ÿå°±æ˜¯æµ‹è¯•å—符类的工具函数。
combining() 函数å�¯ä»¥æµ‹è¯•一个å—符是å�¦ä¸ºå’ŒéŸ³å—符。
在这个模å�—ä¸è¿˜æœ‰å…¶ä»–函数用于查找å—符类别,测试是å�¦ä¸ºæ•°å—å—符ç‰ç‰ã€‚
Unicodeæ˜¾ç„¶æ˜¯ä¸€ä¸ªå¾ˆå¤§çš„ä¸»é¢˜ã€‚å¦‚æžœæƒ³æ›´æ·±å…¥çš„äº†è§£å…³äºŽæ ‡å‡†åŒ–æ–¹é�¢çš„ä¿¡æ�¯ï¼Œ 请看考 Unicode官网ä¸å…³äºŽè¿™éƒ¨åˆ†çš„说明 Ned Batchelder在 他的网站 上对Pythonçš„Unicode处ç�†é—®é¢˜ä¹Ÿæœ‰ä¸€ä¸ªå¾ˆå¥½çš„介ç»�。