了解类变量的引用计数

时间:2012-06-03 22:39:21

标签: python

这是为了更好地理解引用计数在Python中的工作原理。

让我们创建一个类并实例化它。实例的引用计数为1getrefcount显示2,因为它自己的内部结构引用了类实例,引用计数增加1):

>>> from sys import getrefcount as grc
>>> class A():
    def __init__(self):
        self.x = 100000


>>> a = A()
>>> grc(a)
2

a的内部变量x2个引用:

>>> grc(a.x)
3

我希望aA的{​​{1}}方法引用它。然后我决定检查一下。

因此,我在__init__命名空间中创建了一个临时变量b,以便能够访问变量__main__。它将参考号增加x,使其成为1(正如预期的那样):

3

然后我删除了类实例,引用计数减少了>>> b = a.x >>> grc(a.x) 4

1

现在有>>> del a >>> grc(b) 3 引用:一个是2,一个是b(正如我所料)。

A命名空间中删除A我希望计数再次减少__main__

1

但它不会发生。没有类>>> del A >>> grc(b) 3 或其实例可以引用A,但它仍然被100000命名空间中的b以外的其他内容引用。

所以,我的问题是,除__main__之外引用的100000是什么?


BrenBarn 建议我使用b代替可能存储在内部某处的号码。

object()

删除实例>>> class A(): def __init__(self): self.x = object() >>> a = A() >>> b = a.x >>> grc(a.x) 3 >>> del a >>> grc(b) 2 后,a只有一个引用非常符合逻辑。

唯一需要理解的是为什么数字b不是这样。

2 个答案:

答案 0 :(得分:2)

这可能是您使用整数作为测试值的工件。 Python有时会存储整数对象以供以后重用,因为它们是不可变的。当我使用self.x = object()代替运行代码时(这将始终为x创建一个全新的对象)我最后会得到grc(b)==2

答案 1 :(得分:2)

a.x是整数10000.此常量由与__init__()的{​​{1}}方法对应的代码对象引用。代码对象始终包含对代码中所有文字常量的引用:

A

该行

>>> def f(): return 10000
>>> f.__code__.co_consts
(None, 10000)

仅删除名称del A 并减少A的引用次数。在Python 3.x中(但不在2.x中),类通常包含一些循环引用,因此只有在显式运行垃圾收集器时才会收集垃圾。事实上,使用

A

import gc gc.collect() 确实会导致del A的引用次数减少。