您好,登錄后才能下訂單哦!
這篇文章主要介紹“python中函數嵌套、函數作為變量以及閉包的原理是什么”,在日常操作中,相信很多人在python中函數嵌套、函數作為變量以及閉包的原理是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”python中函數嵌套、函數作為變量以及閉包的原理是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
嵌套函數:
python允許創建嵌套函數。也就是說我們可以在函數里面定義函數,而且現有的作用域和變量生存周期依舊不變。
例子:
#encoding=utf-8 def outer(): name="python" def inner():#outer函數內部定義的函數 print name return inner()#返回該內部函數 outer()
結果:
理解:
在inner函數中,python解析器需要找一個叫name的本地變量,查找失敗后會繼續在上層的作用域里面尋找,這個上層作用域定義在outer函數里,python函數可以訪問封閉作用域。
對于outer函數中最后一句,返回inner函數調用的結果,需要知道非常重要一點就是,inner也僅僅是一個遵循python變量解析規則的變量名,python解釋器會優先在outer的作用域里面對變量名inner查找匹配的變量。
把恰好是函數標識符的變量inner作為返回值返回回來,每次函數outer被調用的時候,函數inner都會被重新定義,如果它不被當做變量返回的話,每次執行過后它將不復存在。
在python里,函數就是對象,它也只是一些普通的值而已。也就是說你可以把函數像參數一樣傳遞給其他的函數或者說從函數了里面返回函數
return內層函數時不加括號,只返回函數的地址:
代碼:
#encoding=utf-8 def outer(): name="python" def inner():#outer函數內部定義的函數 return name return inner#返回該內部函數 print outer()
結果:
此時執行外層函數outer(),返回的是內層函數的函數引用(函數名稱)--inner,想要執行內層函數,需要在outer()后邊再加個括號,即outer()(),才會讓內層函數執行
代碼:
#encoding=utf-8 def outer(): name="python" def inner():#outer函數內部定義的函數 return name return inner#返回該內部函數 print outer()
結果:
函數作為變量:
例子:
#encoding=utf-8 def add(x,y): return x+y def sub(x,y): return x-y def apply(func,x,y): return func(x,y) print "apply(add,2,1):",apply(add,2,1) print "apply(sub,2,1):",apply(sub,2,1)
結果:
apply函數準備接收一個函數的變量,它也只是一個普通的變量而已,和其他變量一樣。然后我們調用傳進來的函數:“()代表著調用的操作,并且調用變量包含的值”。
在函數外,我們也能看到傳遞函數并沒有什么特殊的語法,函數的名稱只是和其他變量一樣的表標識符而已。
閉包的理解:
先看個例子
#encoding=utf-8 def outer(): name="python" def inner(): print name return inner res=outer() res() print res.func_closure#打印閉包里包含哪些外部變量
結果:
例中,inner作為一個函數被outer返回,保存在變量res中,并且還能夠調用res()。為什么能調用呢?
通過上面變量的作用域和生存周期我們不難明白,name是函數outer里的一個局部變量,也就是說只有當outer正在運行時,該變量才會存在。
根據python的運行模式,我們是沒法在函數outer執行退出之后還能繼續調用inner函數的,并且在inner函數被調用時,變量name早已不存在了,但是為什么我們調用成功了呢?
這就回到了我們的閉包這個問題上了,python支持一個叫函數閉包的特性。
啥是閉包?
如果一個函數定義在另一個函數的作用域內,并且引用了外層函數的變量,則該函數稱為閉包。閉包是Python所支持的一種特性,它讓在非global scope定義的函數可以引用其外圍空間中的變量,這些外圍空間中被引用的變量叫做這個函數的環境變量。環境變量和這個非全局函數一起構成了閉包。
上例中的inner()函數就是一個閉包,它本身也是一個函數,而且還可以訪問本身之外的變量。這能夠通過查看函數的func_closure屬性得出結論,這個屬性里面包含封閉作用域里面的值(只會包含被捕捉到的值,比如name,如果在outer里面還定義了其他的值,封閉作用域里面是不會有的)
每次函數outer被調用時,inner函數都會被重新定義,上面每次返回的函數inner結果都一樣,因為name沒變。
如下例所示,我們將函數稍微改動一下,結果就不一樣了
代碼:
#encoding=utf-8 def outer(name): def inner(): print name return inner res1=outer("python")#返回閉包 res2=outer("java")#返回閉包 res1()#執行函數 res2()
結果:
分析:
在之前的例子中
def outer(): name="python" def inner(): print name return inner
外層函數后運行后,返回一個函數+函數需要的變量
name = "python" def inner() : print name
上邊三行是整體返回的內容
如果在外層函數再加個外部的整形變量,在里面的函數中引用:
#encoding=utf-8 def outer(): name="python" nbr=12 def inner(): print name print nbr return inner#不加括號就是返回函數對象,不是函數調用 res=outer() res()#調用inner函數 print res.func_closure#打印閉包里包含哪些外部變量
結果:
D:\>python test.py python 12 (<cell at 0x0000000004E56CA8: str object at 0x0000000004E58760>, <cell at 0x0000000004E56F78: int object at 0x0000000004E362C0>)
其中res = outer()是把inner函數對象賦值給res,因為沒有括號,所以不是調用而是返回個函數對象
res()是調用inner函數
print res.func_closure是打印閉包里包含哪些外部變量,可以看到結果里有兩個:即python和12
(<cell at 0x0000000004E56CA8: str object at 0x0000000004E58760>, <cell at 0x0000000004E56F78: int object at 0x0000000004E362C0>)
一個函數返回的函數對象,這個函數對象執行的話依賴非函數內部的變量值,這個時候,函數返回的實際內容如下:
1 函數對象
2 函數對象需要使用的外部變量和變量值
以上就是閉包
閉包必須嵌套在一個函數里,必須返回一個調用外部變量的函數對象,才是閉包
在上邊的例子中,相對于inner來說 ,outer函數就是它得全局變量,就好像你存粹寫個函數會用到函數外面環境定義得全局變量一樣 ,都是相對的概念
通俗理解就是:里面函數執行 ,需要用到外面函數的一個變量 ,所以,就把外面變量和里面這個函數合到一塊,合到一塊的這兩個東西就是閉包
到此,關于“python中函數嵌套、函數作為變量以及閉包的原理是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。