2022-09-10 閉包的使用實例 1 def config_name(name): 2 def inner(msg): 3 print(name + ":" + msg) 4 5 print(id(inner)) 6 return inner 7 8 A = config_name("A") 9 ...
2022-09-10
閉包的使用實例
1 def config_name(name): 2 def inner(msg): 3 print(name + ":" + msg) 4 5 print(id(inner)) 6 return inner 7 8 A = config_name("A") 9 B = config_name("B") 10 A ("有朋自遠方來,不亦樂乎。") 11 B ("都說我如水百變,可知我清澈不變。") 12 13 # 閉包可以對外部函數的變數和參數進行保存
結果圖:
代碼說明:
(1)首先創建了一個閉包函數,即函數嵌套函數,而且在內部函數中使用了外部函數的參數name,在外部函數中的代碼中返回內部函數,註意此處的內部函數返回值與常規調用不同,儘管內部函數是個有參函數,但是此時返回的是一個內部函數的名稱。
♣在閉包函數的定義中,我不太理解為什麼內部函數是一個有參函數,但是返回值時,只是一個單獨的函數名稱,為什麼不要括弧了呢?
☆後來我想了一下,可以這樣理解,在外部函數中創建的內部函數相當於外部函數的一個變數,因此返回時,可以直接返回內部函數的名稱。
(2)創建好閉包函數後,創建閉包實例對象進行測試。調用閉包函數,而且傳一個實參給name,後賦值給一個變數A。因為在閉包函數中還有一個內部函數需要傳參,因此在變數A後直接加括弧,在括弧內寫入要傳入的實參。B變數同理。
結果圖解釋:
(1)第一行與第二行表示的是閉包中的內部函數的記憶體地址,可以看出創建的兩個閉包實例對象的內部函數的存放位置不是相同的。
(2)第三行與第四行輸出的是第3行代碼輸出的內容。
閉包使用中的註意事項:
修改閉包內使用的外部變數
先看一個例圖:
1 def func_out(): 2 num1 = 10 3 def func_inner(): 4 num1 = 20 5 result = num1 + 10 6 print(result) 7 print("修改前的num1:",num1) 8 func_inner() 9 print("修改後的num1:",num1) 10 return func_inner 11 12 new_func = func_out() 13 new_func()
此時的輸出結果:
可以看出在代碼的第4中修改了變數num1的值,但是查看結果圖中“修改後的num1”的值仍然是10.可以看出這樣並沒有改變變數。因為這裡是在內部函數定義了一個局部變數,只是它的名稱與外部變數的值相等而已。所以在外部輸出“修改後的num1”的值仍然是外部變數為10。
♣那麼使用全局變數修飾符“global”呢,修改後的值會不會變呢?
☆使用Python解釋器pycharm驗證後,值仍然還是不會變。為什麼此處全局變數修飾符不起作用呢?可能閉包中的內部函數修改外部變數的值,不支持“gloabl”,不支持這種語法吧。其他的也不知道。
所以想要在閉包中的內部函數中修改外部變數時,要使用什麼呢?
使用關鍵字“nonlocal”。nonloacl是專門用於表名外部嵌套函數內的變數。
so,若需要實現修改閉包內使用的外部變數的需求,上述的代碼可改為:
1 def func_out(): 2 num1 = 10 3 def func_inner(): 4 nonlocal num1 5 num1 = 20 6 result = num1 + 10 7 print(result) 8 print("修改前的num1:",num1) 9 func_inner() 10 print("修改後的num1:",num1) 11 return func_inner 12 13 new_func = func_out() 14 new_func()
此時結果運行圖: