閉包定義:
在乙個外函式中定義了乙個內函式,內函式裡引用了外函式的臨時變數,並且外函式的返回值是內函式的引用。這樣就構成了乙個閉包。
我們先來看乙個簡單的函式:
defouter(a):
b = 10
print(a+b)
這個函式定義了乙個區域性變數b,我們來呼叫這個函式看一下
>>> outer(5)15>>> print
(b)traceback (most recent call last):
file
"", line 1, in
(b)nameerror: name 'b
'isnot defined
可以看到在呼叫完函式outer後,再列印變數b時,會報變數b沒定義。這個我們很容易理解:b是函式outer的乙個區域性變數,呼叫函式結束後,函式的內部所有東西都會釋放掉,還給記憶體,區域性變數都會消失。
我們再來看乙個巢狀函式:
defouter(a):
b = 10
definner():
print(a+b)
return inner
這個函式的返回值是乙個函式物件,也就是inner函式,我們來呼叫下這個函式
>>> demo = outer(5) #返回的是inner函式
>>> demo() #
這裡就相當於執行inner()
15
看到這裡是不是感覺到有點奇怪,執行demo = outer(5)後,就是呼叫outer函式結束了,按道理說這個時候outer函式內的所有東西都會釋放掉,包括區域性變數a,b。那麼為什麼我在執行demo()時,還可以列印出a+b的值呢?
這就是一種特殊情況,按照文章開始處閉包的定義,這個巢狀函式其實就是乙個閉包,它有一種特權:如果外函式在結束的時候發現有自己的臨時變數將來會在內部函式中用到,就把這個臨時變數繫結給了內部函式,然後自己再結束。
我們知道什麼是閉包了,也知道在閉包中外函式會把變數繫結到內函式上,那麼在內函式中能不能修改外函式的變數呢?
我們來試一下:
defouter(a):
b = 10
definner():
b += 1
(b)
return inner
呼叫:
>>> demo = outer(5)>>>demo()
traceback (most recent call last):
file
"", line 1, in
demo()
file
"", line 4, in
inner
b += 1unboundlocalerror: local variable 'b
' referenced before assignment
報錯,看來是不能直接修改,得想其他辦法。
在函式作用域中,我們知道如果要在函式中修改全域性變數,有兩種方法:
同樣,在閉包中也是類似情況,在內函式中想修改外函式繫結到內函式的變數時,也有兩種方法:
defouter(a):
b = 10c = [a] #
把外函式變數修改成列表
definner():
nonlocal b
#nonlocal宣告外函式變數
b += 1c[0] += 1
(b)
(c[0])
return inner
呼叫:
>>> demo = outer(5)>>>demo()
116
python3 理解閉包
閉包 內部函式對外部函式作用域裡變數的引用 非全域性變數 則稱內部函式為 閉包。黃色部分,引用了作用域變數,巢狀在某個函式裡面,外部無法直接呼叫,被封閉起來成乙個包。就是閉包。開始講解,請認真看 請看以下,我想開啟冰箱,這個步驟只需要一次,然後再放入大象,再放入螞蟻,以下 能完成需求嗎?def op...
python3 閉包 第九天python3 閉包
自由變數 未在本地作用域中定義的變數,例如定義在記憶體函式外的外層函式的作用域中的變數 閉包 出現在巢狀函式中,指的是內層函式引用到了外層函式的自由變數,就形成了閉包 示例1 解析 第四行不會報錯,c已經在counter函式中定義過了,而且inc中的使用方式是為c的元素修改值,而不是重新定義 第八行...
python學習筆記 閉包
乙個函式a和乙個函式b,其中b函式位於a函式體內部,同時b函式體內呼叫了b函式之外,a函式之內的其他變數x 包括a中傳遞過來的引數 此時,x稱為b函式的環境變數,b函式和變數x就構成了乙個閉包。而函式b是需要返回的,也就是返回函式b,其中在返回的時候,對a引數x的呼叫也包括在了裡面,有點封閉包含的意...