2017-09-01 62 views
0

第一次瀏覽函數(沒有技術編碼背景)我無法理解一個概念,就像這樣。Mark Lutz讓我有點困惑

一個簡單的函數工廠:

爲了說明這種簡單來說,考慮下面的函數,在交互提示類型:

>>> def maker(N): 
...  def action(X): # Make and return action 
...   return X ** N # action retains N from enclosing scope 
...  return action 

這定義了簡單地生成並返回一個嵌套的外功能函數,而不調用它 - 製造商使行動,但只是返回行動而不運行它。如果我們調用外部函數:

>>> f = maker(2) # Pass 2 to argument N 
>>> f 

.action在0x0000000002A4A158>

我們回到什麼是生成的嵌套函數創建時嵌套DEF運行一個參考。如果我們現在所說的,我們從外部函數回來:

>>> f(3) # Pass 3 to X, N remembers 2: 3 ** 2 
9 
>>> f(4) # 4 ** 2 
16 

我們調用嵌套函數,一個叫機內採取行動。換句話說,我們調用製造商創建並傳回的嵌套函數。 但是,也許這個最不尋常的部分是嵌套函數會記住整數2,即製造商中變量N的值,即使製造商在我們稱之爲動作時返回並退出。實際上,封閉局部作用域中的N保留爲生成的動作所附帶的狀態信息,這就是爲什麼當它稍後被調用時我們恢復其平方的原因。同樣重要的是,如果我們現在再次調用外部函數,我們會返回一個新的嵌套函數,並附帶不同的狀態信息。也就是說,我們得到調用新的功能時,切丁代替平方的說法,但原來仍廣場爲前:

>>> g = maker(3) # g remembers 3, f remembers 2 
>>> g(4) # 4 ** 3 
64 
>>> f(4) # 4 ** 2 

究竟發生在這裏。請給我一個我能理解的視角。

+1

請嘗試改進問題的標題:現在很難弄清楚問題的內容。 –

+0

您的描述是正確的,返回的函數保留一點狀態。這被稱爲詞法閉包,它是一個函數,它包含在創建函數時詞法作用域中的變量,這些變量被「關閉」並與函數一起保存。我不確定你的問題最終是什麼,然而,你問這是如何實施的? – Ukko

+0

另請參見https://stackoverflow.com/q/21959985/124319關於*修改*封閉捕獲的變量 – coredump

回答

1

action就是我們所說的關閉。它是一個函數對象的組合,以及一個包含所謂的變量的值的環境,這些變量是函數主體中使用的非本地名稱。

在這種情況下,action是在包含用於n一個值,它被「繼承」從呼叫到maker其中action定義的環境的封閉件。請注意,對maker的每個調用定義了一個名爲action新函數對象。通過調用maker返回的閉包包含此新函數,並將值n傳遞給maker

實際上,函數和閉包之間幾乎沒有區別;它的行爲與函數完全相同,只是它的一些非本地名稱從它的封閉環境中取值,而不是全局或調用範圍。