2012-11-12 66 views
1

The Hitchhiker’s Guide to Python指出重用變量名是很好的做法。在Python中重用名稱以節省內存

foo = Spam() 
bar = foo.eggs() 

我同意w/it。它使代碼可讀。

如果變量是40 MB的數據會怎麼樣?它會自我複製並總共有80 MB?

foo = buffer # 40 MB. 
bar = foo.resize((50, 50)) # +40? 

我知道,當函數將被執行的內存將被釋放,但我仍然不認爲這是一個好主意,有喜歡的應用程序只可讀性的,因爲一個國家兩次提高內存的使用情況。這就像一個特例,但另一方面,特殊情況不夠特別,是吧?

回答

5

Python分配只是將參考值複製到目標對象。沒有數據複製。 Python變量只是Python系統字典中的名稱以及作爲對象參考值的值。

其實,你應該小心的作業。任何Python分配意味着共享參考值。 Python的分配決不意味着複製目標對象。使用字符串或數字等不可變對象時,不會出現問題。但是,當您分配任何可變對象(列表,字典,集合和某個用戶對象)時,您應該知道在此之後,您只是給目標對象一個不同的名稱(通過另一個參考值副本訪問)。

這同樣適用於將對象作爲函數/方法參數傳遞。

+0

Python中沒有這樣的「變量」。它的所有參考。 – Ber

+0

這是真的,但不是複製可以發生的唯一地方--foo.resize似乎返回它的結果,這意味着它會創建一個新的緩衝區並返回它,而不是就地工作。這意味着這些數據確實可以存在兩次。 – lvc

+0

我明白了。但問題包含'foo = buffer',這是共享。 '.resize'是指向目標的方法。我不知道它究竟做了什麼。如果'bar'是問題的核心,那麼'bar'指向的早期目標被釋放,'bar'被重新用於其他目的。 – pepr

4

如果你絕對必須有一個數據完全之前內存你調整它的大小(而非只在您所關心的位閱讀),你可以這樣做:

foo = buffer() 
bar = foo.resize((50, 50)) 
del foo 

或等價:

bar = buffer().resize((50, 50)) 

這兩個都使buffer的結果立即可用於垃圾收集,只要運行此代碼即可。

此外,在這種情況下重用變量名是完全合理的 - 如果代碼中的行緊接着一個接一個,尤其是如果foo.resize返回與foo相同類型的對象(因爲它似乎),那麼:

foo = buffer 
foo = foo.resize((50, 50)) 

是非常好的。建議是不要將名稱重用爲完全不相關的變量 - 以便讀取代碼的人員可以看到變量,並跳到最初分配的位置以明白它是什麼。當他們中的一個僅僅是一次性的「墊腳石」來獲得你關心的實際對象時,讀者就會感到迷惑。

+0

如果你正在處理大對象,儘早釋放未使用的gc對象,可以使性能發生巨大的變化,特別是在gc可以收集中間函數的多線程代碼中,由於某些其他因素線。如果創建和丟棄的數據是列表或類似的數據,尤其如此,更不用說節省內存。 – Perkins

相關問題