假设我有维护父/子结构的代码。在这样的结构中,我得到循环引用,其中孩子指向父母,父母指向孩子。我应该担心吗?我正在使用Python 2.5。
我担心它们不会被垃圾收集,应用程序最终会占用所有内存。
答案 0 :(得分:32)
__del__
特殊方法。)
因此,引用循环不会影响程序的正确性,但可能会影响其性能和/或占用空间。
如果您想删除不需要的引用循环,通常可以在Python的标准库中使用weakref模块。
如果您想要进行更多关于循环垃圾收集的直接控制(或执行调试,看看究竟发生了什么),请使用Python标准库中的gc模块。
答案 1 :(得分:18)
实验:你很好:
import itertools
for i in itertools.count():
a = {}
b = {"a":a}
a["b"] = b
它一直使用3.6 MB的RAM。
答案 2 :(得分:11)
当没有外部引用时,Python将检测周期并释放内存。
答案 3 :(得分:7)
循环引用是正常的事情,所以我没有理由担心它们。许多树算法要求每个节点都有到其子节点及其父节点的链接。他们还需要实现类似双重链接的列表。
答案 4 :(得分:3)
我认为你不应该担心。尝试以下程序,你会发现它不会占用所有内存:
while True:
a=range(100)
b=range(100)
a.append(b)
b.append(a)
a.append(a)
b.append(b)
答案 5 :(得分:2)
对变量列表中的方法的引用似乎存在问题。这是两个例子。第一个不会调用__del__
。对于__del__
,第二个with weakref是可以的。但是,在后一种情况下,问题是您不能弱引用方法:http://docs.python.org/2/library/weakref.html
import sys, weakref
class One():
def __init__(self):
self.counters = [ self.count ]
def __del__(self):
print("__del__ called")
def count(self):
print(sys.getrefcount(self))
sys.getrefcount(One)
one = One()
sys.getrefcount(One)
del one
sys.getrefcount(One)
class Two():
def __init__(self):
self.counters = [ weakref.ref(self.count) ]
def __del__(self):
print("__del__ called")
def count(self):
print(sys.getrefcount(self))
sys.getrefcount(Two)
two = Two()
sys.getrefcount(Two)
del two
sys.getrefcount(Two)