大于 21 个字符的 CPython 字符串 - 内存分配

CPython strings larger than 21 chars - memory allocation

我想知道这种行为的原因可能是什么(CPython 2.7 和 3.5):

>>> a = 's' ; b = 's'
>>> id(a), id(b)
(4322870976, 4322870976)

少于 21 个字符的字符串似乎共享相同的内存地址(或 ID)。

>>> a = 's' * 20 ; b = 's' * 20
>>> id(a), id(b)
(4324218680, 4324218680)

从 21 日起,这种行为发生了变化。

>>> a = 's' * 21 ; b = 's' * 21
>>> id(a), id(b)
(4324218536, 4324218608)

我找不到合理的解释,但根据 python docs:

E.g., after a = 1; b = 1, a and b may or may not refer to the same object with the value one, depending on the implementation...

看了cpython's code之后,我找不到这个决定是在哪里做出的。

Python 编译器 converts 尽可能多的表达式,并且对字节码中的常量(即它实习)有意义。通过此过程,具有相同值的常量将具有相同的 id()。这给出了第一个和第二个示例中的结果。

但我们必须取得资格"makes sense"。较大的表达式(例如 10**100)会导致大量 space 用于它们的常量结果。这意味着编译器在字节码中包含未修改的表达式,并在运行时计算它们的值。对于字符串(实际上 所有 类型),最大长度为 20,因此第三个示例中的表达式由 VM 而不是编译器计算。