Python> = 3.3内部字符串表示形式

Alberto O .:

我一直在研究PEP 393之后Python如何表示字符串,但我不了解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?字符不足以表示ASCII字符串吗?另外,如果PyASCIIObject已经具有wchar_t指针,为什么PyCompactUnicodeObject也具有char指针?我的理解是两个指针都指向同一位置,但是为什么要同时包含两个指针呢?

内容:

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缓冲区将被保留,因为以后其他想要查找PY_UNICODE字符串的API函数可能会需要使用缓冲区

有趣的是,您现在正在询问CPython的内部字符串表示形式,因为目前正在进行有关是否wchar *可以在即将发布的Python版本中删除不推荐使用的字符串API函数和实现细节(如指针)的讨论尽管计划可能会在此之前发生变化,尤其是如果对野外使用的代码的影响比预期严重的话,看起来Python 3.11.0(可能会在2022年发布)可能会发生这种情况。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章