Python閉包需要注意的問題

2021-07-11 23:41:30 字數 1481 閱讀 6830

python中的閉包從表現形式上定義為:如果在乙個內部函式裡,對在外部作用域(但不是在全域性作用域)的變數進行引用,那麼內部函式就被認為是閉包(closure),也就是說內層函式引用了外層函式的變數然後返回內層函式的情況就稱之為閉包。

閉包的特點是返回的函式還引用了外層函式的區域性變數。所以,要正確使用閉包,就要確保引用的區域性變數在函式返回後不能變。

# 希望返回六個函式,分別計算3*0,3*1,3*2,3*3,3*4,3*5

def operator():

return [lambda m: n * m for n in range(6)]

print [o(3) for o in operator()]

上面的**等同於:

# 希望返回六個函式,分別計算3*0,3*1,3*2,3*3,3*4,3*5

def operator():

fs =

for n in range(6):

def func(m):

return m * n

return fs

print [o(3) for o in operator()]

在內層函式func()中就用到了外層函式的區域性變數n,但是n是變化的,本來我們希望輸出的結果是[0, 3, 6, 9, 12, 15],但實際上輸出的結果是[15, 15, 15, 15, 15, 15]。

原因就是因為n是變化的,當operator()返回這六個函式時,這六個函式引用的n已經變成了5,由於這六個函式未被呼叫,所以未計算m×n,等到被呼叫時n已經變成了5,所以輸出6個15。

這個結果的出現,主要是因為python中的遲繫結(late binding )機制,即閉包中變數的值只有在內部函式被呼叫時才會進行查詢。因此,在上面的**中,每次operator()所返回的函式被呼叫時,都會在附近的作用域中查詢變數n的值(而到那時,迴圈已經結束,所以變數n最後被賦予的值為5)。

那麼該怎麼修改**使得結果符合我們的期望呢。

# 希望返回六個函式,分別計算3*0,3*1,3*2,3*3,3*4,3*5

def operator():

return [lambda m, n=n: n * m for n in range(6)]

print [o(3) for o in operator()]

或者是:

# 希望返回六個函式,分別計算3*0,3*1,3*2,3*3,3*4,3*5

def operator():

fs =

for n in range(6):

def func(m, n=n):

return m * n

return fs

print [o(3) for o in operator()]

輸出:

[0, 3, 6, 9, 12, 15]

需要注意的問題

決策樹id3和c4.5的差別?各自優點?boost演算法 cart 回歸樹用平方誤差最小化準則,分類樹用基尼指數最小化準則 gbdt與隨機森林演算法的原理以及區別。優化演算法中常遇到的kkt條件?作用是?最近鄰演算法knn 分類與回歸 l1和l2函式?l1和l2正則項的比較,如何解決 l1 求導困難...

python 模組和包 需要注意的地方

一 模組 1.import import module 將執行檔案 module 的目錄路徑插入到sys.path的第乙個位置 執行時 1.建立新的命名空間 2.執行被呼叫的模組 第二次呼叫,不會再執行該模組,只是完成一次引用 import語句是可以在程式中的任意位置使用的,且針對同乙個模組很imp...

Qml settings 需要注意的問題

qml 中使用 settings 可以儲存一些簡單的資訊,例如使用者名稱,密碼,視窗位置,大小等,沒有sqlite那麼麻煩,簡單易用哦 環境 qt5.8 for android windows 7 main.qml import qtquick 2.7import qtquick.window 2....