这是为了更好地理解引用计数在Python中的工作原理。
让我们创建一个类并实例化它。实例的引用计数为1
(getrefcount
显示2
,因为它自己的内部结构引用了类实例,引用计数增加1
):
>>> from sys import getrefcount as grc
>>> class A():
def __init__(self):
self.x = 100000
>>> a = A()
>>> grc(a)
2
a
的内部变量x
有2
个引用:
>>> grc(a.x)
3
我希望a
和A
的{{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
不是这样。
答案 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
的引用次数减少。