来自sys.getrefcount的意外结果

use*_*646 5 python garbage-collection

当我输入:

>>> astrd = 123
>>> import sys
>>> sys.getrefcount(astrd)
3
>>> 
Run Code Online (Sandbox Code Playgroud)

我没有得到astrd3次使用的地方?

Tor*_*rek 9

它不是astrd被引用三次,而是值123.astrd只是(不可变)数字123的名称,可以多次引用.除此之外,通常共享小整数:

>>> astrd = 123
>>> sys.getrefcount(astrd)
4
>>> j = 123
>>> sys.getrefcount(astrd)
5
Run Code Online (Sandbox Code Playgroud)

在第二个赋值中,不会创建新的整数,而j只是整数的新名称123.

但是,给定非常大的整数,这不成立:

>>> i = 823423442583
>>> sys.getrefcount(i)
2
>>> j = 823423442583
>>> sys.getrefcount(i)
2
Run Code Online (Sandbox Code Playgroud)

共享整数是CPython(以及其他)的实现细节.由于小整数经常被实例化,因此共享它们可以节省大量内存.这是因为整数首先是不可变的.

对于第二个例子中的附加参考,参见 codeape的答案.


cod*_*ape 7

来自getrefcount docstring:

...返回的计数通常比您预期的高一个,因为它包含(临时)引用作为参数getrefcount().

另外两个引用意味着python内部持有对该对象的两个引用.也许locals()和globals()词典每个都算作一个引用?


Bla*_*ift 6

我认为这是对123的引用,尝试其他例子,比如

>>> import sys
>>> astrd = 1
>>> sys.getrefcount(astrd)
177
>>> astrd = 9802374987193847
>>> sys.getrefcount(astrd)
2
>>> 
Run Code Online (Sandbox Code Playgroud)

9802374987193847的引用数量符合codeape的答案.

这可能是因为数字是不可变的.例如,如果您使用列表,它将始终为2(来自干净的提示).

顺便说一句,我的123也是2,也许你的设置有些不同?或者它可能与时间有关?


Ben*_*oît 5

int以特殊方式实现,它们被缓存和共享,这就是为什么你没有得到1.

而python,使用引用计数对象.astrd本身就是一个引用,所以你实际上得到了int'123'的引用数.尝试使用其他(用户定义的)类型,您将获得1.