为什么这个表情符号在windows(python)上有len的2?

时间:2017-12-27 03:13:42

标签: python unicode

在Windows上:

>>> a = u'\U0001f649'
>>> print a

>>> len(a)
2
>>> a[0]
u'\ud83d'
>>> a[1]
u'\ude49'

在linux上:

>>> a = u'\U0001f649'
>>> print a

>>> len(a)
1
>>> a[0]
u'\U0001f649'

那么为什么\U0001f649会在Windows上转换为\ud83d\ude49?有人可以彻底解释他们之间的整体关系/联系吗?另外,如何在Linux上将\U0001f649转换为\ud83d\ude49

P.S。:两者都在Python 2.6.6上

Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)] on win32

Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36) [GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2

1 个答案:

答案 0 :(得分:4)

这是因为这两个版本使用不同的本机编码进行编译。 Windows版本在内部使用UTF-16,Linux版本在内部使用UCS-4 / UTF-32。

你可以看到差异:

在Windows和OSX上:

>>> import sys
>>> sys.maxunicode
65535

在Linux上,我认为你会得到1114112。

这意味着每个字符在Windows上占用2个字节,在Linux上占用4个字节。如果字符不适合,因为它高于65536,则以UTF-16编码。

对于您的问题,您可以通过以下方式查看两种不同的编码:

[UTF-16]
>>> a = u'\U0001f649'
>>> [hex(ord(x)) for x in a.encode('utf-16be')]  # UTF-16, Big Endian
['0xd8', '0x3d', '0xde', '0x49']

对应于\ ud83d \ ude49,正如您在Windows上看到的那样。

[UTF-32]
>>> [hex(ord(x)) for x in a.encode('utf-32be')] # UTF-32, Big Endian
['0x0', '0x1', '0xf6', '0x49']

对应于\ U0001F649,正如您在Linux上看到的那样。

Wikipedia有一篇关于UTF-16的相当广泛的文章,但基本上,部分代码空间被搁置,并且每个单词中编码完整20位数的10位。

作为旁注,后续版本的Python 3完全取消了这一点。而不是每个字符串都是16位或32位,具体取决于编译时选项:每个字符串是8位,16位或32位,具体取决于字符串中的最大字符。这样效率要高得多,因为程序中的大多数字符串都是ASCII或仅基本多语言平面。