如何在Python 3中迭代Unicode字符?

Ros*_*ith 13 python unicode python-3.x

我需要一次遍历Python字符串一个字符,但是一个简单的"for"循环代替我给UTF-16代码单元:

str = "abc\u20ac\U00010302\U0010fffd"
for ch in str:
    code = ord(ch)
    print("U+{:04X}".format(code))
Run Code Online (Sandbox Code Playgroud)

打印:

U+0061
U+0062
U+0063
U+20AC
U+D800
U+DF02
U+DBFF
U+DFFD
Run Code Online (Sandbox Code Playgroud)

当我想要的是:

U+0061
U+0062
U+0063
U+20AC
U+10302
U+10FFFD
Run Code Online (Sandbox Code Playgroud)

有没有办法让Python给我一系列Unicode代码点,无论字符串是如何在引擎盖下实际编码的?我在这里测试Windows,但我需要能在任何地方使用的代码.它只需要在Python 3上工作,我不关心Python 2.x.

到目前为止我能想出的最好的是:

import codecs
str = "abc\u20ac\U00010302\U0010fffd"
bytestr, _ = codecs.getencoder("utf_32_be")(str)
for i in range(0, len(bytestr), 4):
    code = 0
    for b in bytestr[i:i + 4]:
        code = (code << 8) + b
    print("U+{:04X}".format(code))
Run Code Online (Sandbox Code Playgroud)

但我希望有一种更简单的方法.

(对精确的Unicode术语进行迂腐的挑剔将以四个线索无情地击败头部.我想我已经明确了我在这之后的事情,请不要浪费空间"但是UTF-16是从技术上讲,Unicode也是"一种论点."

Mar*_*nen 7

在Python 3.2.1上使用窄版本的Unicode:

PythonWin 3.2.1 (default, Jul 10 2011, 21:51:15) [MSC v.1500 32 bit (Intel)] on win32.
Portions Copyright 1994-2008 Mark Hammond - see 'Help/About PythonWin' for further copyright information.
>>> import sys
>>> sys.maxunicode
65535
Run Code Online (Sandbox Code Playgroud)

你发现了什么(UTF-16编码):

>>> s = "abc\u20ac\U00010302\U0010fffd"
>>> len(s)
8
>>> for c in s:
...     print('U+{:04X}'.format(ord(c)))
...     
U+0061
U+0062
U+0063
U+20AC
U+D800
U+DF02
U+DBFF
U+DFFD
Run Code Online (Sandbox Code Playgroud)

解决它的方法:

>>> import struct
>>> s=s.encode('utf-32-be')
>>> struct.unpack('>{}L'.format(len(s)//4),s)
(97, 98, 99, 8364, 66306, 1114109)
>>> for i in struct.unpack('>{}L'.format(len(s)//4),s):
...     print('U+{:04X}'.format(i))
...     
U+0061
U+0062
U+0063
U+20AC
U+10302
U+10FFFD
Run Code Online (Sandbox Code Playgroud)

Python 3.3的更新:

现在它按照OP期望的方式工作:

>>> s = "abc\u20ac\U00010302\U0010fffd"
>>> len(s)
6
>>> for c in s:
...     print('U+{:04X}'.format(ord(c)))
...     
U+0061
U+0062
U+0063
U+20AC
U+10302
U+10FFFD
Run Code Online (Sandbox Code Playgroud)