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)

我试图在python中从内存中删除一个对象,但遇到了一个没有被删除的对象。根据我的理解,如果没有对对象的引用,垃圾收集器将在运行时取消分配内存。但是,如果我运行

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将重用内存

好的,多亏了cjhanks和用户2357112,我想出了这个答案

问题是,如果你运行这个程序,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将重用内存

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