1. 程式人生 > >對Python中閉包的理解

對Python中閉包的理解

定義

Python閉包表現為:如果在一個內部函式裡,對在外部作用域(非全域性作用域)的變數進行引用,那麼內部函式就被認為是閉包(closure)。

def outer(a):
    b = 1
    def inner():
        # 內部函式inner中用到了外部函式的變數
        print(a+b)
    #外部函式outer的返回值是內部函式的引用
    return inner

demo = outer(2)
type(demo) # <type 'function'>
demo.__name__ # 'inner'
demo() # 3

一般情況下,一個函式結束的時候,會把自己的臨時變數都釋放還給記憶體,之後變數都不存在了。但是閉包是一個特別的情況。外部函式發現,自己的臨時變數會在將來的內部函式中用到,自己在結束的時候,返回內函式的同時,會把外函式的臨時變數送給內函式繫結在一起。所以外函式已經結束了,呼叫內函式的時候仍然能夠使用外函式的臨時變數。

建立一個Python閉包

Python閉包(closure)必須滿足以下三點標準:

  • 必須有一個內嵌函式
  • 內嵌函式必須用到定義在外部函式內的區域性變數
  • 外部函式必須返回內嵌函式

注意事項

閉包中不能修改外部作用域的區域性變數的,

def outer():
    a = 1
    def inner():
        a = a + 1
        return a
    return inner

demo = outer()
print(demo()) # Error

在閉包inner()中,變數a在賦值符號"="的左面,會被python認為是inner()中的區域性變數,再接下來執行printa()時,程式執行至a = a + 1時,因為先前已經把a歸為inner()中的區域性變數,所以python會在inner()中去找在賦值語句右面的a的值,結果找不到,就會報錯。

如果你非要修改也是可以的,有兩種方法:

def outer():
    b = 1  # a和b都是閉包變數
    c = [3] #這裡對應修改閉包變數的方法2
   
    def inner():
        #內函式中想修改閉包變數
        # 方法1 nonlocal關鍵字宣告
        nonlocal  b
        b += 1

        # 方法2,把閉包變數修改成可變資料型別 比如列表
        c[0] += 1

        print(b)
        print(c[0])
    # 外函式的返回值是內函式的引用
    return inner

demo = outer()
demo() # 2 4
  • 在python3中,可以用nonlocal 關鍵字宣告 一個變數, 表示這個變數不是區域性變數空間的變數,需要向上一層變數空間找這個變數。
  • 在python2中,沒有nonlocal這個關鍵字,我們可以把閉包變數改成可變型別資料進行修改,比如列表。

閉包的作用(待補)

  • 當閉包執行完後,仍然能夠保持住當前的執行環境
  • 閉包可以根據外部作用域的區域性變數來得到不同的結果

參考: