這裏介紹一下python 的閉包python
閉包(closure)是函數式編程的重要的語法結構。編程
函數式編程的一個特色就是,容許把函數自己做爲參數傳入另外一個函數,還容許返回一個函數!閉包
Python對函數式編程提供部分支持。因爲Python容許使用變量,所以,Python不是純函數式編程語言。ssh
閉包(closure)是函數式編程的重要的語法結構。函數式編程是一種編程範式 (而面向過程編程和麪向對象編程也都是編程範式)。編程語言
在面向過程編程中,咱們見到過函數(function);在面向對象編程中,咱們見過對象(object)。函數式編程
函數和對象的根本目的是以某種邏輯方式組織代碼,並提升代碼的可重複使用性(reusability)。函數
閉包也是一種組織代碼的結構,它一樣提升了代碼的可重複使用性。spa
不一樣的語言實現閉包的方式不一樣。Python以函數對象爲基礎,code
爲閉包這一語法結構提供支持的 (咱們在特殊方法與多範式中,已經屢次看到Python使用對象來實現一些特殊的語法)。orm
Python一切皆對象,函數這一語法結構也是一個對象。
在函數對象中,咱們像使用一個普通對象同樣使用函數對象,好比更改函數對象的名字,或者將函數對象做爲參數進行傳遞。
和其餘對象同樣,函數對象也有其存活的範圍,也就是函數對象的做用域。
函數對象是使用def語句定義的,函數對象的做用域與def所在的層級相同。
好比下面代碼,咱們在next函數的隸屬範圍內定義的函數test,就只能在test的隸屬範圍內調用。
def test(): def next(): print('next') print('test') test() # 執行結果 > test
再看下面代碼
def test(): def next(): print('next') next() print('test') next() test() # 執行結果 > next > test > next
函數是一個對象,因此能夠做爲某個函數的返回結果。
def hello(greet): def setName(name): print(greet,name) return setName Hello = hello("Good Morning") Hello('Yang') print(dir(Hello)) print(Hello.__closure__) print(Hello.__closure__[0].cell_contents) print(Hello.__name__) print(id(Hello)) Hellob = hello("Good Afternoon") Hellob('Yang') print(Hello.__name__) print(id(Hellob)) # 執行結果 #> Good Morning Yang #> ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] #> (<cell at 0x0000026D9A8078B8: str object at 0x0000026D9A966370>,) #> Good Morning #> setName #> 1779595040560 #> Good Afternoon Yang #> setName #> 1779595040696
閉包只是在表現形式上跟函數相似,但實際上不是函數。
從代碼的結果中能夠看到,閉包在運行時能夠有多個實例,不一樣的引用環境變量(這裏就是greet變量)和相同的函數(這裏就是setName)組合能夠產生不一樣的實例。
一個函數和它的環境變量合在一塊兒,就構成了一個閉包(closure)。在Python中,所謂的閉包是一個包含有環境變量取值的函數對象。環境變量取值被保存在函數對象的__closure__屬性中。
__closure__裏包含了一個元組(tuple)。這個元組中的每一個元素是cell類型的對象。咱們看到第一個cell包含的就是Good Morning,也就是咱們建立閉包時的環境變量greet的取值。
在Python中建立一個閉包能夠歸結爲如下三點:
經過這三點,就能夠建立一個閉包
def closureFun(): '''閉包''' a = 5 def add(x): # 1 閉包函數必須有內嵌函數 return x + a # 內嵌函數須要引用該嵌套函數上一級中的變量 a return add # 閉包函數必須返回內嵌函數 print(locals()) c = closureFun() # 實例化函數 closureFun 返回 函數add sum = c(6) # 調用add ,並傳參 ,此時返回 x + a = 6 + 5 = 11 print(sum) # 11 print(globals())
Python中的內建函數locals()和globals()能夠用來查看不一樣namespace中定義的元素。
本文介紹瞭如何經過Python建立一個閉包,以及Python建立的閉包是如何工做的。