我正在尝试从python中的内存中删除一个对象,并且我遇到了一个未被删除的对象。根据我的理解,如果没有对该对象的引用,垃圾收集器将在运行时取消分配内存。但是,如果我运行
,我删除了所有引用bar = [foo() for i in range(0, 10)]
for x in range(0,len(bar))
baz = bar[x]
del bar[x]
print gc.get_referrers(baz)
我收到了
的回复并[d帧对象位于0x7f1eba291e50>]
0
那怎么不删除对象?
如果我
,我会得到所有对象实例的相同回复import random, gc
class Object():
def __init__(self):
self.n=None
self.p=None
self.isAlive=True
def setNext(self,object):
self.n=object
def setPrev(self, object):
self.p=object
def getNext(self):
return self.n
def getPrev(self):
return self.p
def simulate(self):
if random.random() > .90:
self.isAlive=False
def remove(self):
if self.p is not None and self.n is not None:
self.n.setPrev(self.p)
self.p.setNext(self.n)
elif self.p is not None:
self.p.setNext(None)
elif self.n is not None:
self.n.setPrev(None)
del self
class Grid():
def __init__(self):
self.cells=[[Cell() for i in range(0,500)] for j in range(0,500)]
for x in range(0,100):
for y in range(0,100):
for z in range(0,100):
self.cells[x][y].addObject(Object())
def simulate(self):
for x in range(0,500):
for y in range(0,500):
self.cells[x][y].simulate()
num=gc.collect()
print " " + str(num) +" deleted today."
class Cell():
def __init__(self):
self.objects = None
self.objectsLast = None
def addObject(self, object):
if self.objects is None:
self.objects = object
else:
self.objectsLast.setNext(object)
object.setPrev(self.objectsLast)
self.objectsLast = object
def simulate(self):
current = self.objects
while current is not None:
if current.isAlive:
current.simulate()
current = current.getNext()
else:
delete = current
current = current.getNext()
if delete.getPrev() is None:
self.objects = current
elif delete.getNext() is None:
self.objectsLast = delete.getPrev()
delete.remove()
def main():
print "Building Map..."
x = Grid()
for y in range (1,101):
print "Simulating day " + str(y) +"..."
x.simulate()
if __name__ == "__main__":
main()
如何从对象中完全删除所有引用/知道所有框架对象是什么?
我认为对象框架(?)包含程序中所有对象的列表但我无法确认/找到一种方法来消除对象被所述神秘的引用(对我而言)对象框架。
非常感谢任何帮助
编辑: 好吧,我把代码改写成简单的形式,除了基础知识之外的所有内容
{{1}}
答案 0 :(得分:0)
好的,谢谢cjhanks和user2357112,我想出了这个答案
问题在于,如果你运行程序,即使删除了某些内容,gc也不会在每天之后收集任何内容
要测试是否已删除,请改为运行
print len(gc.get_objects())
每次我经历一天""这样做表明python正在跟踪多少个对象。 现在有了这些信息并感谢评论我厌倦了将Grid更改为
class Grid():
def __init__(self):
self.cells=[[Cell() for i in range(0,500)] for j in range(0,500)]
self.add(100)
def add(self, num):
for x in range(0, 100):
for y in range(0, 100):
for z in range(0, num):
self.cells[x][y].addObject(Object())
def simulate(self):
for x in range(0,500):
for y in range(0,500):
self.cells[x][y].simulate()
num=gc.collect()
print " " + str(num) +" deleted today."
print len(gc.get_objects())
然后在整个过程中途调用Grid.add(50)。我对程序的内存分配没有增加(在Bash中看顶部)所以我的学习要点:
答案 1 :(得分:0)
gc.get_referrers
接受一个参数:它应该找到它的引用对象。
我无法想到gc.get_referrers
不会返回任何结果的任何情况,因为为了将对象发送到gc.get_referrers
,必须有对该对象的引用。
换句话说,如果没有对该对象的引用,则无法将其发送到gc.get_referrers
。
至少,会有来自globals()
或当前execution frame(包含本地变量)的引用:
代码块在执行帧中执行。执行帧包含一些管理信息(用于调试),确定代码块执行完成后执行的持续时间和方式,并且(可能最重要的是)定义了两个命名空间,即本地和全局命名空间,它们会影响执行代码块。
从问题中查看示例的扩展版本:
class Foo(object):
pass
def f():
bar = [Foo() for i in range(0, 10)]
for x in range(0, len(bar)):
# at this point there is one reference to bar[x]: it is bar
print len(gc.get_referrers(bar[x])) # prints 1
baz = bar[x]
# at this point there are two references to baz:
# - bar refernces it, because it is in the list
# - this "execution frame" references it, because it is in variable "baz"
print len(gc.get_referrers(bar[x])) # prints 2
del bar[x]
# at this point, only the execution frame (variable baz) references the object
print len(gc.get_referrers(baz)) # prints 1
print gc.get_referrers(baz) # prints a frame object
del baz
# now there are no more references to it, but there is no way to call get_referrers
f()
有一个更好的技巧来检测是否有引用:weakref
。
weakref
模块提供了一种创建弱引用的方法,该对象不计算。这意味着即使存在对对象的弱引用,当没有其他引用时它仍将被删除。它也不计入gc.get_referrers
。
所以:
>>> x = Foo()
>>> weak_x = weakref.ref(x)
>>>
>>> gc.get_referrers(x) == [globals()] # only one reference from global variables
True
>>> x
<__main__.Foo object at 0x000000000272D2E8>
>>> weak_x
<weakref at 0000000002726D18; to 'Foo' at 000000000272D2E8>
>>> del x
>>> weak_x
<weakref at 0000000002726D18; dead>
弱引用说对象已经死了,所以它确实被删除了。