cpython的字符串实习有什么规则?

What are the rules for cpython's string interning?

在python 3.5 中,是否可以预测我们何时会获得驻留字符串或何时会获得副本?在阅读了有关此问题的一些 Stack Overflow 答案后,我发现 this one the most helpful but still not comprehensive. Than I looked at Python docs,但默认情况下不保证实习

Normally, the names used in Python programs are automatically interned, and the dictionaries used to hold module, class or instance attributes have interned keys.

所以,我的问题是关于内部 intern() 条件,即决策(是否实习字符串文字):为什么同一段代码在一个系统上工作而不在另一个系统上工作,什么mentioned topic 的答案作者在说

时的意思是什么?

the rules for when this happens are quite convoluted

据我从您链接的 post 中了解到:

当您使用 if a == b 时,您正在检查 a 的值是否为 b 的值,而当您使用 if a is b 时,您正在检查是否ab 是相同的对象(或共享内存中的相同位置)。

现在 python 实习常量字符串(由 "blabla" 定义)。 所以:

>>> a = "abcdef"
>>> a is "abcdef"
True

但是当你这样做时:

>>> a = "".join([chr(i) for i in range(ord('a'), ord('g'))])
>>> a
'abcdef'
>>> a is "abcdef"
False

C 编程语言中,使用带有 "" 的字符串将使其成为 const char *。我认为这就是这里发生的事情。

你认为有规则

实习的唯一规则是 intern 的 return 值被实习。其他一切都取决于决定某段代码应该或不应该进行实习的人的心血来潮。例如,"left"PyCodeNew 实习:

/* Intern selected string constants */
for (i = PyTuple_GET_SIZE(consts); --i >= 0; ) {
    PyObject *v = PyTuple_GetItem(consts, i);
    if (!all_name_chars(v))
        continue;
    PyUnicode_InternInPlace(&PyTuple_GET_ITEM(consts, i));
}

这里的 "rule" 是 Python 代码对象的 co_consts 中的一个字符串对象,如果它纯粹由 [=33=33 中合法的 ASCII 字符组成=] 标识符。 "left" 会被保留,但 "as,df" 不会,而 "1234" 会被保留,即使标识符不能以数字开头。虽然标识符可以包含非 ASCII 字符,但此类字符仍会被此检查拒绝。 实际 标识符永远不会通过此代码;他们无条件地被拘留了几行,ASCII 与否。此代码可能会更改,还有许多其他代码可以执行实习或类似实习的事情。

向我们询问字符串实习的 "rules" 就像向气象学家询问您的婚礼是否下雨的规则。我们可以告诉你很多关于它是如何工作的,但它对你没有多大用处,你总会得到惊喜。