Python 对象能否跟踪其引用?

Python 对象能否跟踪其引用?,python,python-3.x,garbage-collection,Python,Python 3.x,Garbage Collection,我在做蟒蛇3。我遇到了一个奇怪的情况,只有当一个对象有办法判断是否有任何引用时才能解释。然而,这种行为似乎并不影响python2.7。我已经放弃了关于它是垃圾收集问题的解释,因为gc.disable()没有任何区别。只是想澄清一下,这对我来说不是问题,但我真的很想知道到底发生了什么 如果您对特定情况感兴趣,这里有一个MWE 我正在使用从(matplotlib 2.0.0)中截取的代码: 现在,如果我取消注释行timer=None,计时器将不再工作(正如我前面所说,仅在python3中)。另一方

我在做蟒蛇3。我遇到了一个奇怪的情况,只有当一个对象有办法判断是否有任何引用时才能解释。然而,这种行为似乎并不影响python2.7。我已经放弃了关于它是垃圾收集问题的解释,因为
gc.disable()
没有任何区别。只是想澄清一下,这对我来说不是问题,但我真的很想知道到底发生了什么


如果您对特定情况感兴趣,这里有一个MWE

我正在使用从(matplotlib 2.0.0)中截取的代码:

现在,如果我取消注释行
timer=None
,计时器将不再工作(正如我前面所说,仅在python3中)。另一方面,如果我现在取消对另一行的注释,它将按预期工作



顺便说一下,我有两台电脑。一个是在ubuntu 14.04上运行python 3.4.3并使用后端Qt5Agg,另一个是在ubuntu 16.04上运行python 3.5.2并使用后端TkAgg。此行为仅在前者上观察到(我猜它与后端相关)。

如果要获取对象的引用计数,可以使用:

sys.getrefcount(something)
请注意,下面将输出
2
,因为有一个对列表的临时引用

lst = [1, 2, 3]
print(sys.getrefcount(lst))

如果要获取对象的引用计数,则可以使用:

sys.getrefcount(something)
请注意,下面将输出
2
,因为有一个对列表的临时引用

lst = [1, 2, 3]
print(sys.getrefcount(lst))
啊,这(几乎可以肯定)是由于垃圾收集。在CPython中,大量垃圾收集是通过引用计数完成的,这与
gc
模块无关
gc
仅用于收集引用周期中的垃圾,在这种情况下,仅引用计数是无能为力的。例如:

class T:
    def __del__(self):
        print("going away")

t = T()
print("before")
t = None  # remove only reference to the object
print("after")
在CPython发布的每个版本下(即使是在
gc
之前),都会打印:

before
going away
after
before
after
现在,让爱好者:

x = T()
y = T()
x.ref = y
y.ref = x
print("before")
x, y = None, None
print("after")

import gc
gc.collect()
print("after gc")
这里的
x
指的是
y
,反之亦然。这是一个“循环”。每一个都可以从另一个访问,因此它们的引用计数永远不会低于1(除非
x.ref
和/或
y.ref
也为1)。所以在所有版本的CPython下,都会打印:

before
going away
after
before
after
起初。在Python 3下,它将继续打印:

going away
going away
after gc
after gc
但在Python 2下,它只会继续打印:

going away
going away
after gc
after gc
这是由于循环垃圾中包含具有
\uu del\uu
方法的对象的一个模糊的技术问题;Python2不能回收它们,但Python3可以

唉,我不可能准确地猜出你的例子中发生了什么。这需要研究两种实现下的
fig.canvas.new_timer
的源代码

但底线很清楚:如果您需要一个对象保持活动状态,请确保可以从代码中访问它。在它变得不可访问之后,一个或另一个垃圾收集子系统可以随时销毁它。

啊,它(几乎可以肯定)是由于垃圾收集。在CPython中,大量垃圾收集是通过引用计数完成的,这与
gc
模块无关
gc
仅用于收集引用周期中的垃圾,在这种情况下,仅引用计数是无能为力的。例如:

class T:
    def __del__(self):
        print("going away")

t = T()
print("before")
t = None  # remove only reference to the object
print("after")
在CPython发布的每个版本下(即使是在
gc
之前),都会打印:

before
going away
after
before
after
现在,让爱好者:

x = T()
y = T()
x.ref = y
y.ref = x
print("before")
x, y = None, None
print("after")

import gc
gc.collect()
print("after gc")
这里的
x
指的是
y
,反之亦然。这是一个“循环”。每一个都可以从另一个访问,因此它们的引用计数永远不会低于1(除非
x.ref
和/或
y.ref
也为1)。所以在所有版本的CPython下,都会打印:

before
going away
after
before
after
起初。在Python 3下,它将继续打印:

going away
going away
after gc
after gc
但在Python 2下,它只会继续打印:

going away
going away
after gc
after gc
这是由于循环垃圾中包含具有
\uu del\uu
方法的对象的一个模糊的技术问题;Python2不能回收它们,但Python3可以

唉,我不可能准确地猜出你的例子中发生了什么。这需要研究两种实现下的
fig.canvas.new_timer
的源代码


但底线很清楚:如果您需要一个对象保持活动状态,请确保可以从代码中访问它。在它变得不可访问之后,一个或另一个垃圾收集子系统可以随时销毁它。

因此,在这种情况下,计时器可能正在检查sys.getrefcount(self)。有趣。因此,在本例中,计时器可能正在检查sys.getrefcount(self)。有趣。我一直认为,
gc.disable()
完全阻止了垃圾收集。因此有两个垃圾收集器,
gc.disable()
只停止其中一个。引用计数(RC)系统是基本的,不能关闭——Python程序通常以惊人的速度创建新对象,如果没有RC系统,大多数程序将很快耗尽内存。distinct
gc
系统仅用于循环回收垃圾(RC系统太弱,无法识别它们)。我一直认为
gc.disable()
完全阻止了垃圾收集。因此有两个垃圾收集器,
gc.disable()
只停止其中一个。引用计数(RC)系统是基本的,不能关闭——Python程序通常以惊人的速度创建新对象,如果没有RC系统,大多数程序将很快耗尽内存。独特的
gc
系统仅用于循环回收垃圾(RC系统太弱,无法识别它们)。