sys.getrefcount的结果出乎意料

5
当我输入时:
>>> astrd = 123
>>> import sys
>>> sys.getrefcount(astrd)
3
>>> 

我不知道 astrd 在哪里被使用了3次?

4个回答

10

引用了三次的不是astrd,而是值123astrd只是一个(不可变的)数字123的名称,可以被引用多次。另外,小整数通常是共享的:

>>> astrd = 123
>>> sys.getrefcount(astrd)
4
>>> j = 123
>>> sys.getrefcount(astrd)
5
在第二个赋值操作中,并没有创建一个新的整数,相反,j 只是指向整数 123 的新名称。
然而,对于非常大的整数,这种情况并不成立:
>>> i = 823423442583
>>> sys.getrefcount(i)
2
>>> j = 823423442583
>>> sys.getrefcount(i)
2

共享整数是CPython(以及其他一些实现)的一个实现细节。由于小整数经常被实例化,共享它们可以节省大量内存。这是因为整数本身是不可变的。

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


7
getrefcount文档字符串中可以得知:

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

另外两个引用表示Python内部持有对象的两个引用。也许locals()和globals()字典每个都算一个引用?


当我执行“del astrd”时,它的引用计数变为0,然后被垃圾回收器收集? - user46646

6

我认为它计算了对123的引用次数,尝试其他示例,例如

>>> import sys
>>> astrd = 1
>>> sys.getrefcount(astrd)
177
>>> astrd = 9802374987193847
>>> sys.getrefcount(astrd)
2
>>> 

9802374987193847的引用计数符合codeape的答案。

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

顺便说一句,我对123也得到了2,也许您的设置有所不同?或者可能与时间有关?


5

整数在 Python 中是以一种特殊的方式实现的,它们被缓存和共享,这就是为什么你不会得到 1 的原因。

而且 Python 使用引用计数对象。astrd 本身就是一个引用,所以你实际上得到的是对整数 '123' 的引用数。尝试使用另一种(用户定义的)类型,你将得到 1。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接