Python 3.x中字符串的内部表示是什么

the*_*bat 24 python string unicode python-3.x

在Python 3.x中,字符串由Unicode序数项组成.(请参阅下面的语言参考中的引文.)Unicode字符串的内部表示是什么?是UTF-16吗?

字符串对象的项是Unicode代码单元.Unicode代码单元由一个项的字符串对象表示,并且可以包含表示Unicode序数的16位或32位值(序数的最大值在sys.maxunicode中给出,并取决于Python的方式在编译时配置).代理对可能存在于Unicode对象中,并将作为两个单独的项报告.

Tob*_*obu 25

Python 3.3中的内部表示将改变,它实现了PEP 393.新的表示将选择一个或几个ascii,latin-1,utf-8,utf-16,utf-32,通常试图获得紧凑的表示.

只有在与传统API(那些仅存在于Windows上,其中wchar_t为两个字节)的情况下,才会进行代理对的隐式转换; Python字符串将被保留.这是发行说明.

  • 在我看来,PEP 393表示内部表示是ASCII,Latin-1(UCS1),UCS2或UCS4中最紧凑的(给定特定字符串).即:特别是不是utf-8/16/32.原因是:Python必须是索引到字符串的恒定时间,因此字符必须是统一大小,UCS就是这种情况,但utf表示不是这种情况. (6认同)
  • Latin-1是ASCII的超集,因此没有理由将ASCII作为选项之一。选项为(a)统一为8位,即Latin-1,(b)统一为16位,即UCS2,或(c)统一为32位,即UCS4(与UTF-32相同)。明显排除的是UTF-8和UTF-16,它们每个代码点的位数都不相同 (3认同)

Mat*_*ett 10

在Python 3.3及更高版本中,字符串的内部表示将取决于字符串,并且可以是ascii,latin-1,utf-8,utf-16,utf-32中的任何一个,如Tobu所述并在PEP 393中描述.

对于以前的Pythons,内部表示依赖于Python的构建标志.可以使用标志值--enable-unicode=ucs2或构建Python --enable-unicode=ucs4. ucs2实际上,build 使用UTF-16作为内部表示,而ucs4build使用UCS-4/UTF-32.


cod*_*ape 6

查看CPython 3.1.5的源代码,在Include/unicodeobject.h:

/* --- Unicode Type ------------------------------------------------------- */

typedef struct {
    PyObject_HEAD
    Py_ssize_t length;          /* Length of raw Unicode data in buffer */
    Py_UNICODE *str;            /* Raw Unicode buffer */
    long hash;                  /* Hash value; -1 if not set */
    int state;                  /* != 0 if interned. In this case the two
                                 * references from the dictionary to this object
                                 * are *not* counted in ob_refcnt. */
    PyObject *defenc;           /* (Default) Encoded version as Python
                                   string, or NULL; this is used for
                                   implementing the buffer protocol */
} PyUnicodeObject;
Run Code Online (Sandbox Code Playgroud)

字符存储为数组Py_UNICODE.在大多数平台上,我相信Py_UNICODE#define这样的wchar_t.


Joh*_*hin -1

Python 2.X 和 3.X 之间的 Unicode 内部表示没有变化。

它绝对不是 UTF-16。UTF-anything 是一种面向字节的 EXTERNAL 表示形式。

每个代码单元(字符、代理等)都被分配了一个范围 (0, 2 ** 21) 中的数字。这称为它的“序数”。

确实,您引用的文档说明了一切。大多数 Python 二进制文件使用 16 位序数,这将您限制在基本多语言平面(“BMP”),除非您想用代理进行处理(如果您找不到您的衬衫并且您的指甲床已被去除,这很方便)生锈了)。为了使用完整的 Unicode 指令集,您更喜欢“宽构建”(32 位宽)。

简而言之,unicode 对象的内部表示是一个 16 位无符号整数数组,或一个 32 位无符号整数数组(仅使用 21 位)。

  • “以 16 位整数存储 unicode 代码点”被称为“UCS-2”。UCS-4 对 32 位整数做同样的事情。 (23认同)
  • “没有任何变化……”。实际上,请参阅 PEP 393(2010 年 1 月),其中详细说明了随后发生的变化,以及此处的另一个答案“内部表示将发生变化......” (7认同)
  • @约翰:我不明白你想说什么。如果编码不是“存储 Unicode 代码点的方式”(或者更一般地说是字符信息),那么它是什么编码。是的,我很清楚 UTF-16 是 UCS-2 的现代替代品,但它与你所说的不一样。UTF-16 支持所有 Unicode,但 UCS-2 仅支持 BMP。 (6认同)
  • 这个答案是错误的,请参阅下面Tobu的答案。PEP 393 是在给出此答案一个月后编写的。 (5认同)
  • “UTF-anything 是一种面向字节的外部表示”。在某些系统中,它也是有效的内部表示。例如,在许多基于 C++ 的系统中,UTF-8 在内部使用,而不仅仅是用于 I/O。Go 专门使用 UTF-8 作为内部字符串表示。 (5认同)