Python 拉丁字符与Unicode
我有一个树形结构,其中的关键词可能包含一些拉丁字符。我有一个函数,它会遍历树的所有叶子节点,并在满足某些条件时将每个关键词添加到一个列表中。
这是我用来将这些关键词添加到列表中的代码:
print "Adding: " + self.keyword
leaf_list.append(self.keyword)
print leaf_list
如果这个关键词是 université
,那么我的输出是:
Adding: université
['universit\xc3\xa9']
看起来打印函数可以正确显示拉丁字符,但当我把它添加到列表时,它却被解码了。
我该如何改变这个情况?我需要能够打印出包含标准拉丁字符的列表,而不是它们的解码版本。
2 个回答
当你打印一个列表时,你看到的是列表里面每个项目的repr
,对于字符串来说,这个repr
和它们实际的内容是不同的:
>>> a = ['foo', 'bär']
>>> print(a[0])
foo
>>> print(repr(a[0]))
'foo'
>>> print(a[1])
bär
>>> print(repr(a[1]))
'b\xc3\xa4r'
repr
的输出是为了程序员方便看的,而不是普通用户方便看的,所以它会显示引号和十六进制代码。如果你想以更友好的方式打印一个列表,可以自己写一个循环。例如:
>>> print '[', ', '.join(a), ']'
[ foo, bär ]
你现在手里没有Unicode对象,而是一些用UTF-8编码的字节字符串。如果你的终端设置支持UTF-8文本,打印这些字节字符串可能会正常工作。
当你把一个列表转换成字符串时,列表里的内容会以一种“表现形式”显示出来,这就是repr()
函数的结果。字符串对象的表现形式会用转义码来表示那些不在可打印ASCII范围内的字节;比如换行符会被替换成\n
。你的UTF-8字节会用\xhh
这样的转义序列来表示。
如果你使用的是Unicode对象,表现形式仍然会用\xhh
转义,但只针对拉丁-1范围内的Unicode码点(也就是不在ASCII范围内的部分);其他的则会用\uhhhh
和\Uhhhhhhhh
来表示,具体取决于它们的码点。当打印时,Python会自动将这些值编码成你终端所需的正确编码:
>>> u'université'
u'universit\xe9'
>>> len(u'université')
10
>>> print u'université'
université
再来看看字节字符串:
>>> 'université'
'universit\xc3\xa9'
>>> len('université')
11
>>> 'université'.decode('utf8')
u'universit\xe9'
>>> print 'université'
université
注意,é
这个码点的长度也反映出它被编码成了两个字节。顺便说一下,当我把é
字符粘贴到Python会话中时,是我的终端把\xc3\xa9
字节提供给了Python,因为它被设置为使用UTF-8,而Python在我定义u'..'
这个Unicode对象字面量时检测到了这一点并解码了这些字节。
我强烈建议你阅读以下文章,以了解Python如何处理Unicode,以及Unicode文本和编码字节字符串之间的区别:
每个软件开发者绝对必须了解的Unicode和字符集的最低限度知识(没有借口!) 由Joel Spolsky撰写
务实的Unicode 由Ned Batchelder撰写