未命名的整数文字的意外引用计数

时间:2017-01-06 16:35:17

标签: python

据我所知,在CPython 2.x和3.x中,有些整数是单例:

>>> a = 256; a is 256    # or any integer from -5 to 256
True

>>> a = 257; a is 257    # or any other integer outside the magic range
False

因此,如果我在-5到256范围内的整数上运行sys.getrefcount,我发现很多导入的包都引用了这个整数:

>>> sys.getrefcount(1)
1470

我也理解sys.getrefcount比你预期的更多返回1,因为它的自己的引用了参数:

>>> a = 257; sys.getrefcount(a)
2

我没有得到的是:

>>> sys.getrefcount(257)
3

为什么3,而不是2?我可以理解我可能已经在我自己的范围内创建了一个临时变量(计数1),并且显然sys.getrefcount会添加另一个自己的引用(计数2)但是第三个来自哪里,并且为什么在前面的例子中没有发生?更重要的是:是否存在可能发生这种情况的其他情况,导致可能误解sys.getrefcount输出?

以上所有内容都可以在64位Python 2.7.12和3.5.1上由Anaconda复制,在OSX上运行,也可以在Windows上运行的32位Python 2.7.5发行版上复制。但是,在较旧的Python版本(Windows上的32位Python 2.5.4)上,sys.getrefcount(257)返回2,这对我来说是更多的预期。

1 个答案:

答案 0 :(得分:3)

您在此处遇到了一个实施细节。编译器通常可以缓存不可变的文字值:

>>> import dis
>>> compile("sys.getrefcount(257)", '', 'single').co_consts
(257, None)
>>> dis.dis(compile("sys.getrefcount(257)", '', 'single'))
  1           0 LOAD_NAME                0 (sys)
              2 LOAD_ATTR                1 (getrefcount)
              4 LOAD_CONST               0 (257)
              6 CALL_FUNCTION            1
              8 PRINT_EXPR
             10 LOAD_CONST               1 (None)
             12 RETURN_VALUE

'single'是交互式解释器使用的模式。)

我们在这里看到3个引用;一个来自代码对象上的co_consts元组,一个位于堆栈上(来自LOAD_CONST指令),另一个来自sys.getrefcount()方法本身。