9

当我需要向用户输出某些内容时,我知道我在使用 Unicode 和编码为 UTF-8 时,我对我的 Python 世界感到很高兴。然后,我的一位同事给我发了“The UTF-8 Everywhere' manifesto”(2012 年),这让我很困惑。

  • 这篇文章的作者多次声称 UCS-2(Python 使用的 Unicode 表示)是 UTF-16 的同义词。
    • 他甚至直接说 Python 使用 UTF-16 进行内部字符串表示。
  • 作者还承认自己是 Windows 爱好者和开发人员,并指出 MS 多年来处理字符编码的方式导致该组最困惑,所以也许这只是他自己的困惑。我不知道...

有人可以解释一下 UTF-16 与 Unicode 在 Python 中的状态吗?它们是同义词吗?如果不是,以什么方式?

4

1 回答 1

22

Python 中 Unicode 字符串的内部表示(从 2.2 到 3.2 的版本)取决于 Python 是在模式还是模式下编译的。大多数 Python 版本都很窄(您可以检查一下sys.maxunicode——窄版本上是 65535,宽版本上是 1114111)。

对于宽版本,字符串是 4 字节宽字符的内部序列,即它们使用 UTF-32 编码。所有代码点的长度都是一个宽字符。

在狭窄的构建中,字符串是使用 UTF-16 的 2 字节宽字符的内部序列。BMP 以外的字符(代码点 U+10000 及以上)使用通常的 UTF-16 代理对存储:

>>> q = u'\U00010000'
>>> len(q)
2
>>> q[0]
u'\ud800'
>>> q[1]
u'\udc00'
>>> q
u'\U00010000'

请注意,UTF-16 和 UCS-2 并不相同。UCS-2 是一种固定宽度编码:每个代码点都被编码为 2 个字节。因此,UCS-2不能对超出 BMP 的代码点进行编码。UTF-16 是一种可变宽度编码;BMP 之外的代码点使用一对字符进行编码,称为代理对。


请注意,随着PEP 393的实施,这一切都在 3.3 中发生了变化。现在,Unicode 字符串使用足够宽的字符来表示,以容纳最大的代码点——ASCII 字符串为 8 位,BMP 字符串为 16 位,否则为 32 位。当使用许多纯 ASCII 字符串时,这消除了宽/窄分隔并有助于减少内存使用量。

于 2012-10-26T23:03:33.250 回答