在python中转义unicode字符串

Jos*_*e G 4 python unicode python-2.7

在python中这三个命令打印相同的表情符号:

print "\xF0\x9F\x8C\x80"

print u"\U0001F300"

print u"\ud83c\udf00"

Run Code Online (Sandbox Code Playgroud)

如何在\ x,\ u和\ U转义之间进行转换?我无法想象这些十六进制数是如何相等的?

wim*_*wim 8

第一个是字节字符串:

>>> "\xF0\x9F\x8C\x80".decode('utf8')
u'\U0001f300'
Run Code Online (Sandbox Code Playgroud)

u"\ud83c\udf00"一个是UTF-16版本(四位Unicode转义)

u"\U0001F300"一个是码点的实际索引.


但数字如何相关? 这是一个棘手的问题.它由编码定义,没有明显的关系.为了给你一个想法,这里是一个"手动"编码索引0x1F300的代码点为UTF-8的例子:

旋风字符的索引为0x1f300,其范围为0x00010000 - 0x001FFFFF.此范围的模板是:

11110... 10...... 10...... 10......
Run Code Online (Sandbox Code Playgroud)

在哪里用代码点的二进制表示填充点.我无法告诉你为什么模板看起来像那样,它只是utf-8的定义.

这是我们的代码点的二进制表示:

>>> u''
u'\U0001f300'
>>> unichr(0x1f300)
u'\U0001f300'
>>> bin(0x1f300)
'0b11111001100000000'
Run Code Online (Sandbox Code Playgroud)

因此,如果我们采用字符串模板并将其填充(带有一些前导零,因为模板中有更多的插槽而不是我们编号中的有效数字),我们得到:

11110... 10...... 10...... 10......
11110000 10011111 10001100 10000000
Run Code Online (Sandbox Code Playgroud)

现在让我们将其转换回十六进制

>>> 0b11110000100111111000110010000000
4036988032
>>> hex(4036988032)
'0xf09f8c80'
Run Code Online (Sandbox Code Playgroud)

在那里你有代码点的UTF8表示.

对于UTF16 ,您的代码点有一个类似的魔术配方:从索引中减去0x10000,然后我们用零填充以获得20位二进制表示.前十位被添加到0xD800以给出第一个16位代码单元.最后十位被添加到0xDC00以给出第二个16位代码单元.

>>> bin(0x1f300 - 0x10000)[2:].rjust(20, '0')
'00001111001100000000'
>>> _[:10], _[10:]
('0000111100', '1100000000')
>>> hex(0b0000111100 + 0xd800)
'0xd83c'
>>> hex(0b1100000000 + 0xdc00)
'0xdf00'
Run Code Online (Sandbox Code Playgroud)

还有你的UTF 16版本,即带有小写版本的版本\u.

您可能已经理解,这些表示中的十六进制数字之间可能没有明显的数字关系,它们只是同一代码点的不同编码.

  • 四个1表示编码长度为4个字节.10开始每个延续字节. (2认同)