为什么复杂 class 没有优化缓存 Python 中的对象?

Why is complex class not optimized to cache objects in Python?

据我所知,正常情况下 Python 会缓存对象以优化内存使用。例如:

>>> a = 7
>>> b = 7
>>> hex(id(a)) == hex(id(b))
True

它甚至适用于字符串。所以我想知道为什么 complex 对象不是内置对象时的情况,我认为应该尽可能优化它们。

>>> a = 1+3j
>>> b = 1+3j
>>> hex(id(a)) == hex(id(b))
False

这是故意的还是complex数字的内部表示复杂来做到这一点?

id是一个显示对象内存位置的函数。从 -5256 are cached in memory 的所有 Python 整数用于再利用(无论如何它们都是不可变的对象)所以你展示的第一个例子应该有相同的 id对于 ab。如果你尝试使用更大的整数,你将不会得到这个结果,因为生成整数不会缓存任何东西。只有那些整数是预先缓存的。

在第二个示例中,解释器在每次调用 1 + 3j 时生成不同的复数对象,因为此操作中也没有缓存。

PS:一种更简单的检查方法是使用 is 关键字:

>>> a = 9992
>>> b = 9992
>>> a is b
False

有时候,这些事情会发生:

>>> 9992 is 9992
True

这是因为在 CPython 的 Peephole Optimizer 上,它使用相同的常量来加载 9992 的两个版本,然后进行比较。检查下面的反汇编代码(两者 LOAD_CONST 使用索引 1 引用同一对象)。

>>> def f():
...    return 9992 is 9992

>>> dis.dis(f)
2           0 LOAD_CONST               1 (9992)
            3 LOAD_CONST               1 (9992)
            6 COMPARE_OP               8 (is)
            9 RETURN_VALUE

关于字符串,CPython(在 2.6 及更高版本上)有一个自动 intern 功能也可以缓存一些结果。但是不能保证你每次写相同的字符串时都有相同的对象,并且当你有字符串操作(如连接)时根本没有机会。


阅读 Ashwini Chaudhary 的评论,我意识到人们可能会混淆常量优化 ("Compile time") 和对象缓存 ("Run Time")。在 Python 文件上,如果您进行上述测试,它们可能 return 为真,因为优化器两次看到相同的数字并创建一个 CONST,如上面的反汇编代码所示。但这只发生在相同的范围内。

为了证明这一点,您可以在 .py 文件中包含以下代码,您会看到整数不会被缓存

def f():
    return 777

def g():
    return 777

print(f() is g())