在Python中向Unicode字符串添加补充代码点
unichr(0x10000)
这个命令在没有使用 --enable-unicode=ucs4
选项编译的 cpython 中会失败,并出现 ValueError
错误。
有没有一种语言内置的或者核心库的函数,可以把任意的 unicode 标量值或代码点转换成 unicode
字符串,并且不管程序运行在哪种 Python 解释器上都能正常工作?
1 个回答
好的,下面是内容:
>>> unichr(0xd800)+unichr(0xdc00)
u'\U00010000'
关键点是,unichr()
这个函数可以把一个整数转换成Python解释器字符串编码中的一个单一字符。根据Python 2.7.3的标准库文档,内置函数部分关于unichr()
的说明,
它会返回一个单个字符的Unicode字符串,这个字符的Unicode编码是整数i……有效的参数范围取决于Python的配置——可能是UCS2 [0..0xFFFF]或UCS4 [0..0x10FFFF]。否则会抛出
ValueError
错误。
我特别强调了“单个字符”,这里的意思是在Unicode术语中是“一个代码单元”。
我假设你在使用Python 2.x版本。Python 3.x版本没有内置的unichr()
函数。相反,Python 3.3.0的标准库文档,内置函数部分关于chr()
的说明是:
它会返回一个表示字符的字符串,这个字符的Unicode编码点是整数i……有效的参数范围是从0到1,114,111(0x10FFFF,十六进制表示)。
注意,返回值现在是一个长度不确定的字符串,而不是一个单一代码单元的字符串。所以在Python 3.x中,chr(0x10000)
的表现会如你所期待的那样。它“将任意的unicode标量值或编码点转换为一个unicode
字符串,这个字符串在任何Python解释器上都能正常工作”。
回到Python 2.x。如果你使用unichr()
来创建Python 2.x的unicode
对象,并且你使用的Unicode标量值超过0xFFFF,那么你的代码就需要关注Python解释器对unicode
对象的实现。
你可以通过一个函数来隔离这种关注,这个函数会尝试对一个标量值使用unichr()
,如果捕获到ValueError
错误,就会用相应的UTF-16代理对再试一次:
def unichr_supplemental(scalar):
try:
return unichr(scalar)
except ValueError:
return unichr( 0xd800 + ((scalar-0x10000)//0x400) ) \
+unichr( 0xdc00 + ((scalar-0x10000)% 0x400) )
>>> unichr_supplemental(0x41),len(unichr_supplemental(0x41))
(u'A', 1)
>>> unichr_supplemental(0x10000), len(unichr_supplemental(0x10000))
(u'\U00010000', 2)
不过你可能会觉得直接把标量值转换成4字节的UTF-32值,然后将这个UTF-32字节string
解码成unicode
字符串更简单:
>>> '\x00\x00\x00\x41'.decode('utf-32be'), \
... len('\x00\x00\x00\x41'.decode('utf-32be'))
(u'A', 1)
>>> '\x00\x01\x00\x00'.decode('utf-32be'), \
... len('\x00\x01\x00\x00'.decode('utf-32be'))
(u'\U00010000', 2)
上面的代码是在Python 2.6.7上测试的,使用UTF-16编码的Unicode字符串。我没有在使用UTF-32编码的Python 2.x解释器上测试它。不过,它应该在任何Python 2.x解释器和任何Unicode字符串实现上都能正常工作。