5

这是为了更好地理解引用计数在 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

a我希望它被A's__init__方法引用。然后我决定检查一下。

所以我b__main__命名空间中创建了一个临时变量,只是为了能够访问该变量x。它增加了 ref-number 以1使其成为3(如预期的那样):

>>> b = a.x
>>> grc(a.x)
4

然后我删除了类实例,引用计数减少了1

>>> del a
>>> grc(b)
3

所以现在有2参考资料:一个是by b,一个是by A(如我所料)。

A通过从命名空间中删除,__main__我希望计数再次减少1

>>> del A
>>> grc(b)
3

但它不会发生。没有A可以引用的类或其实例100000,但它仍然被命名空间以外的东西b引用__main__

所以,我的问题是,100000除了引用什么b


BrenBarn建议我应该使用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非常合乎逻辑的引用。

唯一需要理解的是为什么它不是这样的 number 100000

4

2 回答 2

3

a.x__init__()是整数 10000。这个常量被 的方法对应的代码对象引用A。代码对象总是包含对代码中所有文字常量的引用:

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

线

del A

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

import gc
gc.collect()

afterdel A确实导致b.

于 2012-06-03T22:48:35.057 回答
2

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

于 2012-06-03T22:46:28.747 回答