Python >= 3.3内部字符串表示

8

我正在了解Python在PEP 393之后如何表示字符串,但我不明白PyASCIIObject和PyCompactUnicodeObject之间的区别。

我的理解是,字符串是用以下结构表示的:

typedef struct {
    PyObject_HEAD
    Py_ssize_t length;          /* Number of code points in the string */
    Py_hash_t hash;             /* Hash value; -1 if not set */
    struct {
        unsigned int interned:2;
        unsigned int kind:3;
        unsigned int compact:1;
        unsigned int ascii:1;
        unsigned int ready:1;
        unsigned int :24;
    } state;
    wchar_t *wstr;              /* wchar_t representation (null-terminated) */
} PyASCIIObject;

typedef struct {
    PyASCIIObject _base;
    Py_ssize_t utf8_length;
    char *utf8;
    Py_ssize_t wstr_length;
} PyCompactUnicodeObject;

typedef struct {
    PyCompactUnicodeObject _base;
    union {
        void *any;
        Py_UCS1 *latin1;
        Py_UCS2 *ucs2;
        Py_UCS4 *ucs4;
    } data;                 
} PyUnicodeObject;

如果我理解有误,请纠正我,我认为PyASCIIObject仅用于仅包含ASCII字符的字符串,PyCompactUnicodeObject使用PyASCIIObject结构,用于至少包含一个非ASCII字符的字符串,而PyUnicodeObject用于传统函数。这样说对吗?

此外,为什么PyASCIIObject使用wchar_t?一个char不足以表示ASCII字符串吗? 另外,如果PyASCIIObject已经有了wchar_t指针,为什么PyCompactUnicodeObject还需要一个char指针?我的理解是两个指针都指向相同的位置,但为什么要同时包含两个指针?

1个回答

6

PEP 373 真的是您问题的最佳参考资料,虽然有时候 C-API 文档 也是必要的。让我们逐一回答您的问题:

  1. 您已经正确理解了类型。但有一个不明显的细节:当您使用任何一种“紧凑型”(即PyASCIIObjectPyCompactUnicodeObject)时,结构本身只是一个标头。字符串的实际数据存储在内存中的结构之后。数据使用的编码由kind字段描述,并且将取决于字符串中最大的字符值。

  2. 前两个结构中的wstrutf8指针是用于存储变换表示(如果C代码请求)的地方。对于ASCII字符串(使用PyASCIIObject),不需要为UTF-8数据缓存指针,因为ASCII数据本身与UTF-8兼容。宽字符缓存仅由弃用的函数使用。

    这两个缓存指针永远不会指向相同的位置,因为它们的类型不直接兼容。对于紧凑字符串,它们仅在调用需要UTF-8缓冲区(例如PyUnicode_AsUTF8AndSize)或Py_UNICODE缓冲区(例如弃用的PyUnicode_AS_UNICODE)的函数时分配。

    对于使用弃用的基于Py_UNICODE的API创建的字符串,wstr指针有一个额外的用途。在调用字符串上的PyUnicode_READY宏之前,它指向字符串数据的唯一版本。第一次准备字符串时,将创建一个新的data缓冲区,并使用Latin-1、UTF-16和UTF-32中最紧凑的编码之一存储字符。wstr缓冲区将被保留,因为其他弃用的API函数可能稍后需要查找PY_UNICODE字符串。

很有趣,你现在正在询问CPython的内部字符串表示,因为目前正在讨论{{link1:是否可以在即将发布的Python版本中删除已弃用的字符串API函数和实现细节,例如 wchar *指针。看起来可能会在Python 3.11.0中发生(预计将于2022年发布),但在那之前,计划仍可能发生变化,特别是如果对正在使用的代码产生的影响比预期更严重。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接