07.05 看了這些,別再說你不懂Python了!

新手在初學函數閉包的概念時非常容易迷糊,尤其涉及到閉包的作用域和參數問題,那麼接下來我們就著重講一下Python的嵌套和閉包。

看了這些,別再說你不懂Python了!

python有一個很有意思的地方,就是def函數可以嵌套在另一個def函數之中。調用外層函數時,運行到的內層def語句僅僅是完成對內層函數的定義,而不會去調用內層函數,除非在嵌套函數之後又顯式的對其進行調用。

x = 99

def f1():

x = 88

def f2():

print(x)

f2()

f1()

88

可以看出,f1中的嵌套變量x覆蓋了全局變量x=99,然後f2中的本地變量按照引用規則,就引用了x=88。

看了這些,別再說你不懂Python了!

下面我們來說說嵌套作用域的一個特殊之處:

本地作用域在函數結束後就立即失效,而嵌套作用域在嵌套的函數返回後卻仍然有效。

def f1():

x = 88

def f2():

print(x)

return f2

action = f1()

action()

88

從這裡可以看出函數f1中定義了函數f2,f2引用了f1嵌套作用域內的變量x,並且f1將函數f2作為返回對象進行返回。最值得注意的是我們通過變量action獲取了返回的f2,雖然此時f1函數已經退出結束了,但是f2仍然記住了f1嵌套作用域內的變量名x。

看了這些,別再說你不懂Python了!

上面這種語言現象稱之為閉包:一個能記住嵌套作用域變量值的函數,儘管作用域已經不存在。這裡有一個應用就是工廠函數,工廠函數定義了一個外部的函數,這個函數簡單的生成並返回一個內嵌的函數,僅僅是返回卻不調用,因此通過調用這個工廠函數,可以得到內嵌函數的一個引用,內嵌函數就是通過調用工廠函數時,運行內部的def語句而創建的。

def maker(n):

k = 8

def action(x):

return x ** n + k

return action

f = maker(2)

print(f)

<function>.action at 0x00000000021C51E0>/<function>

這裡接著說說另一個關鍵字nonlocal

本地函數通過global聲明對全局變量進行引用修改,那麼對應的,內嵌函數內部想對嵌套作用域中的變量進行修改,就要使用nonlocal進行聲明。

def test(num):

in_num = num

def nested(label):

nonlocal in_num

in_num += 1

print(label, in_num)

return nested

F = test(0)

F('a')

F('b')

F('c')

a 1

b 2

c 3

這裡我們可以看到幾個點,我們在nested函數中通過nonlocal關鍵字引用了內嵌作用域中的變量in_num,那麼我們就可以在nested函數中修改他,即使test函數已經退出調用,這個“記憶”依然有效。

好啦,學會了嗎,喜歡的話請幫小編點點關注哦!更多精彩內容請關注百戰程序員!

看了這些,別再說你不懂Python了!


分享到:


相關文章: