什麼是閉包?
- 閉包是指在一個函數中定義了一個另外一個函數,內函數裏運用了外函數的臨時變量,並且外函數的返回值是內函數的引用,這樣就構成了一個閉包 。
- 閉包的使用,可以隱藏內部函數的工作細節,只給外部使用者提供一個可以執行的內部函數的引用。
- 注意:裝飾器是用於拓展已有函數功能的一種函數,這個函數的特殊之處在於它的返回值也是一個函數,實際上就是利用閉包語法實現的。
在Pyhton中,函數也是一個對象,在函數操作中,函數對象也可以當成一個參數或一個返回值進行返回, 當程序內或程序外拿到參數的引用後就可以直接使用這個函數。
那閉包到底是什麼呢?現在就來實現一個簡單的閉包
實現一個閉包
def myFunc():
n = '我是myFunc()函數的變量n'
def show():
print('內函數show()輸出:', n)
return show
s = myFunc()
s()
# 運行效果
# 內函數show()輸出: 我是myFunc()函數的變量n
表層
將 show 函數封裝在了 myFunc 函數內部,使外部不可見,不能使用 show 函數,隱藏了實現細節。
內部
- n 是一個 myFunc 函數中的局部變量,正常情況下 myFunc 函數執行結束後,n 就會被釋放。
- 但是現在因爲 callFunc 函數中返回了 show 函數,show 函數在外部還會再執行,所以程序會將 show 函數所需的執行環境保存下來。
- 這種形式就是閉包
如何在內部函數修改外部函數的變量
這裏有個注意點:修改不等於賦值,修改是改變原變量的引用,而賦值是讓變量指向了新的引用,並沒有改變原變量的引用。
通過代碼來看吧:
首先看賦值:
def myFunc():
m = 1
n = 2
def show():
print('m的值爲:', m)
n = 10
print('n的值爲:', n)
return show
s = myFunc()
s()
# 執行效果:
# m的值爲: 1
# n的值爲: 10
可見,賦值操作沒有任何問題,那修改呢?
def myFunc():
m = 1
n = 2
def show():
print('m的值爲:', m)
# nonlocal n #如果不加會報錯。
n += 10
print('n的值爲:', n)
return show
s = myFunc()
s()
執行效果:
將代碼中的註釋‘# nonlocal n #如果不加會報錯。’打開:
nonlocal
- 如果在閉包的內部函數中直接使用外部函數的變量時,不需要任何操作,直接使用就可以了。
- 但是如果要修改外部變量的值,需要將變量聲明爲 nonlocal
- nonlocal 聲明變量爲非本地變量,如果確定在程序要修改外部變量,那麼建議將 nonlocal 寫在內部函數的第一行。
總結
閉包就是在一個外部函數中定義了一個內部函數,並且在內部函數中使用了外部函數的變量,並返回了內部函數。