2012-07-27 29 views
7

在c/C++中,當你在一個函數中創建一個局部變量時,你有堆棧中的變量。python創建堆的一切?

http://effbot.org/zone/call-by-object.htm

CLU對象獨立存在程序的激活。對象的空間 是從一個動態存儲區域分配的../..在理論上,所有對象都是永久存在的。實際上,當對象不再可用於任何CLU程序的 時,可以回收對象使用的空間。

這是否意味着python中的對象是從堆中創建的(就像在c/C++中的malloc一樣)?當沒有與它們相關的名字時,對象被釋放(像智能指針)?

例子:

def foo(a): 
    result = [] 
    result.append(a) 
    return result 

foo("hello") 

myList = foo("bye") 

所以第一個結果([])是在堆上創建和釋放得到,因爲沒有與它相關聯的名字嗎?

+0

如果您認爲需要,您還可以使用'del'手動刪除東西。 – 2012-07-27 13:48:39

+0

如果你問這個問題的動機是你希望你的函數總是使用同一個列表,注意你可以將它定義爲'def foo(a,result = [])',並且每次你使用同樣的列表調用該函數,因爲它在函數定義時創建,而不是在運行時創建。 – geoffspear 2012-07-27 14:26:28

回答

12

是的,所有的Python對象都生活在堆上(至少在CPython上)。它們是引用計數的:當對象的最後一個引用消失時它們被解除分配。 (CPython也有垃圾收集器來打破循環)

在CPython中,函數返回後第一個列表將消失,因爲您沒有將返回值綁定到名稱並且引用計數降爲零。在其他實現中,對象可能會活得更長,直到垃圾收集器啓動。

某些對象(如打開的文件)具有附加的資源,當對象被釋放時會自動釋放資源,但由於上述原因,不建議依靠這個。資源應在您完成後明確關閉。

5

是的,CPython中的所有值都分配在堆上並進行引用計數以知道何時釋放它們。與C不同的是,在大多數情況下,沒有辦法知道一個值是否會超過它的功能,所以唯一安全的做法是堆分配一切。

當然,你可以做一些分析和確定某些值永遠不會傳遞給函數,因此無法逃脫,但那是在Python有限使用的和額外的開銷可能不會是值得的。

4

爲補充其他的答案,這裏有一個方法,來跟蹤,當垃圾收集發生使用特殊的方法__del__

class Test(object): 
    def __init__(self, name): 
     self.name = name 

    def __del__(self): 
     print "deleting {0}".format(self.name) 

print "discarded instance creation" 
Test("hello") 

print "saved instance creation" 
myList = Test("bye") 

print "program done" 

輸出:

 
discarded instance creation 
deleting hello 
saved instance creation 
program done 
deleting bye 

對於更深入數據,請參閱gc module