Python unichr帮助信息有误?怎么处理32位的字符串?

木头r 发布于 2012/07/23 12:17
阅读 1K+
收藏 0

高手解答下面的内容是不是问题?

unichr把一个值转换成对应的字符串。i的范围应该是0xffff内。为什么help(unichr)中写的是0x10ffff呢?(ValueError: unichr() arg not in range(0x10000) (narrow Python build))

>>> help(unichr)
Help on built-in function unichr in module __builtin__:

unichr(...)
    unichr(i) -> Unicode character
    
    Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.

>>> unichr(0x100000)
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
ValueError: unichr() arg not in range(0x10000) (narrow Python build)
另外有一个问题,有一个汉字32位unicode的,值是u'\U0002F80A'

怎么把u'\U0002F80A'转换成0x2f80a,(ord转换不了)

怎么把0x2f80a转换成u'\U0002F80A' (unichr转换不了)

32位的unicode总是被视为2个16位来处理。怎么让他以1个32位处理呢?

比如:
s = u'\U0002F80A\U0002F80B\U0002F80C'

for word in s:

    print word

本来是3个32位的字符,结果被for了6个16位的字符。

怎么解决32位字符串问题呢?

加载中
0
deleted
deleted
编译python的时候指定--enable-unicode=ucs4
木头r
木头r
找到了关于这个的说明。必须重新build python是挺悲剧的?
木头r
木头r
http://san-yun.iteye.com/blog/1544123
0
n
neko1990

unicode和ordinal的转换问题在python2里能通过自定义函数解决。

narrow Python build(使用默认的--enable-unicode=ucs2),虽然它的参数是ucs2,但python内部编码并不是ucs2,是由w_char确定的一般是utf-16(ucs2无法表示除了基本多语言平面(BMP)的字符,utf-16完全取代了ucs2)。当这个unicode不在BMP时,它是以surrogate pairs的形式保存,所以可以看到

>> u'\U0002F80A'[0]
u'\ud87e'
>>> u'\U0002F80A'[1]
u'\udc0a'
  • "怎么把0x2f80a转换成u'\U0002F80A' (unichr转换不了) ",这个方法来自于stackoverflow
    def unichr_supplemental(scalar):
         try:
             return unichr(scalar)
         except ValueError:
             return unichr( 0xd800 + ((scalar-0x10000)//0x400) ) \
                   +unichr( 0xdc00 + ((scalar-0x10000)% 0x400) )
    >>> unichr_supplemental(0x2f80a)
    u'\U0002f80a'
  • "把u'\U0002F80A'转换成0x2f80a"
    def ord_supplemental(unichar):
        try:
            return ord(uc)
        except TypeError:
            return ((ord(uc[0]) - 0xd800) << 10) + \
                   + ord(uc[1]) - 0xdc00 + 0x10000
    >>> hex(ord_supplemental(u'\U0002F80A'))
    '0x2f80a'
  • 最后一个问题,自定义一个generator
    def unicode_generator(us):
       i = 0
       n = len(us)
       while i<n:
          cur = ord(us[i])
          if cur < 0xd800 or cur > 0xdfff:
             yield cur
             i+=1
          else:
             yield ((cur - 0xd800) << 10) + \
                + ord(us[i+1]) - 0xdc00 + 0x10000
             i+=2
    >>> s=u'\U0002F80A\U0002F80B\U0002F80C喵喵123'
    >>> for word in unicode_generator(s):
    ...   print word
    ...
    194570
    194571
    194572
    21941
    21941
    49
    50
    51



返回顶部
顶部