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

标签 python python-3.x memory cpython

我想知道这种行为的原因是什么(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()。这给出了第一个和第二个示例中的结果。

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

关于python - 大于 21 个字符的 CPython 字符串 - 内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37842114/

相关文章:

c - 使用结构进行动态内存分配

android - 没有 SD 卡功能的平板电脑的内存限制

c - 为什么我在 sbrk 之后会遇到无效内存?

python - 在 Python 2.7 中引发异常后未释放对象

python - 使用 lambda 深复制索引整数

python - 在 C++ 中的 PyObject 上调用 `+=`

python - 如果我已经将模型作为 pickle,为什么还需要在 docker 容器中使用 sklearn?

python - Tensorflow中 `tf.function`和 `autograph.to_graph`是什么关系?

python - 如何在不破坏 pip freeze 的情况下链接到 distutils 中的 fork 包?

python - 在 python 中 float