2011-06-11 36 views
10

在SO中有幾個Python垃圾回收的線程,在閱讀了大約五篇文章以及一些文檔之後,我仍然不確定垃圾回收是如何工作的以及如何管理我沒有使用的對象。事實上,我讀過的某個人不應該做任何關於收集垃圾的事情,其他人告訴我應該有一個對象,而另外一些人則解釋說,去引用一個對象足以讓Python將其收集爲垃圾。如何將對象提供給python垃圾回收?

因此,冒着造成重複的風險,我會再次提出這個問題,但不同的是,希望得到更全面和更清晰的信息。

在我的情況下,我想用代表人物的對象進行小型模擬。將創建Person()類的幾個實例。它應該存在一段時間,直到它實際上「死亡」而其他實例將被創建。

現在我該如何讓這個Person()實例「死亡」(假設許多這些實例將被創建,並且我不希望這些實例像幽靈一樣掛出)?

有幾種方式我可以參考的對象:

john = Person('john') 

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

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

是什麼讓我的程序清潔,釋放資源的最佳途徑最佳?那麼引用我的對象的最佳方式是什麼,以便我可以控制對象的刪除?

+0

檢查gc模塊:http://docs.python.org/library/gc.html – rubik 2011-06-11 10:18:30

+1

簡短的回答是:您沒有。當你不再使用(有一個參考)時,它會自動使用它。或者也許以後或從未。 GC不是確定性的,唯一的保證是,如果有垃圾可以重用,則不會耗盡內存(除了某些情況下使用保守的GC,但是Python和其他內存管理語言都不需要使用這些;只有使用指針算術的語言或指針以整數等方式轉義的方式需要這些)。除非你明白這一點,爲什麼你通常不需要擔心,那麼你應該放棄這一點。 – delnan 2011-06-11 10:59:06

+0

這個問題同樣適用於ruby,Smalltalk,Java,C#或VB6以及其他許多應用程序。 – quamrana 2011-06-11 11:09:36

回答

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這樣可以讓一個人保持活力,你可以讓其他物體保持只有這個人的名字)。

+0

感謝這一個:) – Benjamin 2011-06-11 11:55:27

7

這與垃圾回收沒有任何關係。

Python的內存管理的主要方法使用引用計數

在上述所有情況中,Python保留對該對象的所有引用的計數,並且當沒有剩餘對象時,該對象被刪除(類似於C++中的std::shared_pointer)。當

  1. 對象容納他們要麼是明確刪除(通過del
  2. 或超出範圍(see also here (esp. ex. 8))

    引用得到降低

對您而言,這適用於john對象或people容器中的任一個。它們在創建它們的函數結束時超出範圍(假設它們不是調用函數的return)。絕大多數時候,你可以讓它們超出範圍 - 只有當你創建了非常重的對象或集合時 - 比如在一個大循環中 - 你可能想要明確地考慮使用del。例如,當一個對象是指本身 -

垃圾收集當有參考週期 實際上只發揮了作用。像:

a = [] 
a.append(a) 

再次,這是自動發生的,你不應該做任何特殊的事情。

+0

謝謝:)所有答案都非常好,我選擇了Quamrana's,因爲他給出了一個與問題示例更一致的答案。 – Benjamin 2011-06-11 11:54:07

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 

Refrences:del method; gc module; weakref module

+0

謝謝:)所有答案都非常好,我拿起了Quamrana的,因爲他給出了一個更符合問題的例子的答案。 – Benjamin 2011-06-11 11:52:26

+0

@Benjamin:很高興你得到你的答案:) – mouad 2011-06-11 11:54:11