如何将对象转移到python垃圾回收?

时间:2011-06-11 09:57:02

标签: python reference garbage-collection

在SO垃圾收集中有几个线程,在阅读了大约5个,加上一些文档在线后,我仍然不确定垃圾收集的工作原理以及我应该如何管理我不使用的对象。实际上我读过的地方不应该做任何关于收集垃圾的事情,其他人告诉一个应该del个对象,而其他人再次解释解除引用一个对象就足以让Python把它收集起来作为垃圾。

因此,冒着创建副本的风险,我会再次提出问题,但不同的是,希望能够获得更全面,更清晰的信息。

在我的情况下,我想用代表人物的物体进行小型模拟。将创建Person()类的几个实例。它应该存在一段时间,直到它实际上“死”,而其他实例将被创建。

现在我如何让这个Person()实例“死”(假设会创建很多这些实例,我不希望这些实例像鬼一样挂出)?

我可以通过多种方式引用对象:

john = Person('john')

people = []
people.append(Person('john'))

people = {}
people['john'] = Person('john')

保持程序清洁,以最佳方式释放资源的最佳方法是什么?那么引用我的对象以便控制删除对象的最佳方法是什么?

4 个答案:

答案 0 :(得分:9)

也许这也有帮助:

>>> # Create a simple object with a verbose __del__ to track gc.
>>> class C:
...     def __del__(self):
...         print "delete object"
... 
>>> c = C()
>>> # Delete the object c successfully.
>>> del c
delete object
>>> # Deletion of an object when it go out of the scope where it was defined.
>>> def f():
...     c = C()
...
>>> f()
delete object
>>> c = C()
>>> # Create another reference of the object.
>>> b = c
>>> # The object wasn't destructed the call of del only decremented the object reference. 
>>> del c
>>> # Now the reference counter of the object reach 0 so the __del__ was called. 
>>> del b
delete object
>>> # Create now a list that hold all the objects.
>>> l = [C(), C()]
>>> del l
delete object
delete object
>>> # Create an object that have a cyclic reference.
>>> class C:
...     def __init__(self):
...         self.x = self
...     def __del__(self):
...         print "delete object"
... 
>>> c = C()
>>> # Run the garbage collector to collect object.
>>> gc.collect()
9
>>> # the gc.garbage contain object that the gc found unreachable and could not be freed.  
>>> gc.garbage
[<__main__.C instance at 0x7ff588d84368>]
>>> # Break the cyclic reference.
>>> c.x = None
>>> # And now we can collect this object.
>>> del c
delete object
>>> # Create another object with cyclic reference.
>>> c = C()
>>> # When closing the interactive python interpreter the object will be collected.
delete object

参考:del method; gc module; weakref module

答案 1 :(得分:8)

这些都与垃圾收集无关。

Python的主要内存管理方法是使用引用计数

在上面的所有情况中,Python都会保留对该对象的所有引用的计数,如果没有剩下的,则删除该对象(类似于C ++中的std::shared_pointer)。

时引用减少
  1. 持有它们的对象要么明确删除(通过del
  2. 或超出范围(see also here (esp. ex. 8))
  3. 在您的情况下,这适用于john对象或people个容器中的任何一个。它们在创建它们的函数末尾超出范围(假设它们不是return到调用函数)。在绝大多数情况下,你可以让它们超出范围 - 只有当你创建非常重的对象或集合时 - 比如在一个大循环中 - 你可能想要明确地使用del来考虑。

    垃圾收集实际上只有在参考周期时才会发挥作用 - 例如,当一个物体引用自身时。像:

    a = []
    a.append(a)
    

    同样,这会自动发生,您不需要做任何特别的事情。

答案 2 :(得分:4)

我发现大多数程序都很自然地创建和处理对象,因此我通常不会担心它。

一些例子:

person = Person('john')
person = Person('james')
# Whoops! 'john' has died!

people = []
people.append(Person('john'))
# ...
# All 'Persons' live in people
people = []
# Now all 'Persons' are dead (including the list that referenced them)

class House():
    def setOwner(self, person):
        self.owner = person

house.setOwner(people[0])
# Now a House refers to a Person
people = []
# Now all 'Persons' are dead, except the one that house.owner refers to.

我认为你所追求的是:

people = {}
people['john'] = Person('john')

def removePerson(personName):
    del people[personName]

removePerson('john')

在这种情况下,people是主列表,您可以控制何时添加Person并从列表中删除(其字典)。

你可能必须仔细考虑被创造者的概念,然后彻底死亡:一旦创建,人们首先如何与模拟进行交互。死后,你应该如何解开参考文献? (对于一个人来说,可以参考其他东西,例如我的例子中的House之类的东西可以让人活着。你可以让其他对象只持有这个人的名字。)

答案 3 :(得分:0)

以前的答案是正确的,但是根据python 3.7 Document,建议这样做:

“ Python会执行自动内存管理(对大多数对象进行引用计数并进行垃圾回收以消除循环)。在删除最后一个引用后不久,便释放了该内存。”

如果由于内存管理问题确实需要执行此操作,请导入 gc 库,然后执行此操作

     del self.someInstanceOfyourClass
             gc.collect()

这是一个简单的示例https://github.com/nanoseconds/PythonTest/blob/master/test.py