Python对象正被我找不到的对象引用
我试图在python中从内存中删除一个对象,但遇到了一个没有被删除的对象。根据我的理解,如果没有对对象的引用,垃圾收集器将在运行时取消分配内存。但是,如果我运行Python对象正被我找不到的对象引用,python,object,garbage-collection,Python,Object,Garbage Collection,我试图在python中从内存中删除一个对象,但遇到了一个没有被删除的对象。根据我的理解,如果没有对对象的引用,垃圾收集器将在运行时取消分配内存。但是,如果我运行 bar = Foo() print gc.get_referrers(bar) del bar baz = gc.collect() print baz 我得到的答复是 [处的帧对象] 0 那么它为什么不删除对象呢 如果我这样做的话,所有对象的实例都会得到相同的答复 bar = [foo() for i in range(0, 10)
bar = Foo()
print gc.get_referrers(bar)
del bar
baz = gc.collect()
print baz
我得到的答复是
[<0x7f1eba291e50>处的帧对象]
0
那么它为什么不删除对象呢
如果我这样做的话,所有对象的实例都会得到相同的答复
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)
我如何从一个对象中完全删除所有引用器/知道所有对象上的帧对象是什么吗
我原以为是对象框(?)包含程序中所有对象的列表,但我无法确认/找到一种方法使对象不被(对我来说)神秘对象框引用
任何帮助都将不胜感激
编辑:
好的,我把代码改写成简单的形式,除了基本的内容外,我把所有的东西都写了出来
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()
好的,多亏了cjhanks和user2357112,我想出了这个答案 问题是,如果你运行这个程序,gc每天都不会收集任何东西,即使有东西被删除了 为了测试它是否被删除,我改为运行
print len(gc.get_objects())
每过一天,我都会看到python跟踪了多少对象。
现在有了这些信息,多亏了一条评论,我厌倦了将网格更改为
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。在过程中途添加(50)。我的程序内存分配没有增加(在Bash中查看top),因此我的学习点:
- GC在我不知情的情况下运行
- 内存被分配,并且在程序完成之前不会返回到系统
- Python将重用内存
print len(gc.get_objects())
每过一天,我都会看到python跟踪了多少对象。
现在有了这些信息,多亏了一条评论,我厌倦了将网格更改为
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。在过程中途添加(50)。我的程序内存分配没有增加(在Bash中查看top),因此我的学习点:
- GC在我不知情的情况下运行
- 内存被分配,并且在程序完成之前不会返回到系统
- Python将重用内存
gc.get\u referers
接受一个参数:它应该找到其referers的对象
我想不出在任何情况下,gc.get\u referers
都不会返回任何结果,因为要将对象发送到gc.get\u referers
,必须有对该对象的引用
换句话说,如果没有对该对象的引用,则无法将其发送到gc.get\u referers
至少,会有一个来自globals()
或当前(包含局部变量)的引用:
代码块在执行帧中执行。执行框架包含一些管理信息(用于调试),确定代码块执行完成后在何处以及如何继续执行,并且(可能最重要的是)定义两个影响代码块执行的名称空间,即本地名称空间和全局名称空间
请参见问题中示例的扩展版本:
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\u referers
因此:
>x=Foo()
>>>弱x=weakref.ref(x)
>>>
>>>gc.get_referers(x)=[globals()]#仅来自全局变量的一个引用
真的
>>>x
>>>弱x
>>>德尔克斯
>>>弱x
弱引用表示该对象已死亡,因此它确实已被删除。
gc.get\u referers
接受一个参数:它应该找到其referers的对象
我想不出在任何情况下,gc.get\u referers
都不会返回任何结果,因为要将对象发送到gc.get\u referers
,必须有对该对象的引用
换句话说,如果没有对该对象的引用,则无法将其发送到gc.get\u referers
至少,会有一个来自globals()
或当前(包含局部变量)的引用:
代码块在执行帧中执行。执行框架包含一些管理信息(用于调试),确定代码块执行完成后在何处以及如何继续执行,并且(可能最重要的是)定义两个影响代码块执行的名称空间,即本地名称空间和全局名称空间
请参见问题中示例的扩展版本:
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\u referers
因此:
>x=Foo()
>>>弱x=weakref.ref(x)
>>>
>>>gc.get_referers(x)=[globals()]#仅来自全局变量的一个引用
真的
>>>x
>>>弱x
>>>德尔克斯
>>>弱x