2009-12-28 26 views
0

什麼時候創建函數局部變量?例如,在下面的代碼中,是每次調用函數f1時創建的字典d1,還是編譯時只創建一次?什麼時候創建函數本地python變量?

def f1(): 
    d1 = {1: 2, 3: 4} 
    return id(d1) 

d2 = {1: 2, 3: 4} 
def f2(): 
    return id(d2) 

它是在一般更快,以限定功能範圍內的字典或全局定義它(假設字典用於僅在該功能)。我知道查找全局符號比查找本地符號要慢,但如果字典很大,該怎麼辦?

我見過的很多python代碼似乎都是在全球範圍內定義這些字典,這似乎並不是最優的。但是,如果您有一個擁有多個'encoding'方法的類,每個類都有一個獨特的(大型)查找字典,那麼讓代碼和數據在整個文件中傳播是非常尷尬的。

回答

2

局部變量在分配給,即在執行該功能期間被創建。

如果函數的每次執行都需要(並且不修改! - )相同的字典,在函數被調用之前創建一次會更快。作爲替代全局變量,具有缺省值假的說法是,甚至(輕微)更快,因爲它的訪問速度是一個局部變量,但也創造了一次(在def時間):

def f(x, y, _d={1:2, 3:4}): 

我使用名稱_d,帶有前導下劃線,指出它的意思是作爲函數的私有實現細節。儘管如此,它有點脆弱,因爲笨拙的calles可能意外地錯誤地傳遞了三個參數(第三個參數在函數內綁定爲_d,可能會導致bug),或者函數的主體可能錯誤地更改了_d,所以這只是建議當分析顯示真正需要時使用優化。全球字典也會出現錯誤的改動,所以即使它比每次調用重新創建本地字典都快,您仍然可以選擇後一種可能性來實現更高的穩健性(儘管全球字典解決方案,加上良好的單元測試功能中的任何「哎呀」是推​​薦的選擇;-)。

+0

是有道理的。你會推薦使用函數/方法/類屬性來懶惰地建立一個字典,當它第一次被調用? – speeedfrk

+0

@speedfrk,在非常具體的條件下:字典的構建成本非常高,有一個合理的機會,你永遠不需要在給定的運行中創建它,而且你已經在一個類(或其方法)中,所以有一個自然的地方「停放」字典建成時。 –

0

如果你看看dis模塊的反彙編,你會發現d1的創建和填充是在每次執行時完成的。鑑於字典是可變的,這種情況不太可能在短期內發生變化,至少在對Python虛擬機進行良好的逃避分析之前。另一方面,全局常量的查找將通過下一代Python虛擬機進行推測優化,例如unladen-swallow(推測部分是它們是常量)。

+0

良好的洞察力。期待unladen-swallow :-) – speeedfrk

0

速度與你所做的相關。如果你正在編寫一個數據庫密集型應用程序,我懷疑你的應用程序會受到你選擇的全局變量或局部變量的影響。使用探查器來確保。 ;-)

正如Alex指出的那樣,調用函數時會初始化當地人。作爲簡單的方法來證明你自己:

import random 

def f(): 
    d = [random.randint(1, 100), random.randint(100, 1000)] 
    print(d) 

f() 
f() 
f() 
+0

這與我的示例字典是'常量'不完全相同 - 只包含文字不可變的鍵和值,從不變異,並且不會從函數返回。 – speeedfrk