python 閉包

在這里談談我的淺顯認識:要形成閉包,首先得有一個嵌套的函數,即函數中定義了另一個函數。
閉包則是一個集合,它包括了外部函數的局部變量,這些局部變量在外部函數返回后也繼續存在,并能被內部函數引用

舉個例子

這是個經常使用到的例子,定義一個函數generate_power_func
,它返回另一個函數,現在閉包形成的條件已經達到。

def generate_power_func(n):
   print "id(n): %X" % id(n)
   def nth_power(x):
       return x**n
   print "id(nth_power): %X" % id(nth_power) 
   return nth_power

對于內部函數nth_power,它能引用到外部函數的局部變量n,而且即使generate_power_func已經返回。把這種現象就稱為閉包。具體使用一下。

>>> raised_to_4 = generate_power_func(4)
id(n): 246F770id
(nth_power): 2C090C8
>>> repr(raised_to_4)
'<function nth_power at 0x2c090c8>'

從結果可以看出,當generate_power_func(4)
執行后, 創建和返回了nth_power
這個函數對象,內存地址是 0x2C090C8,并且發現raised_to_4
和它的內存地址相同,即raised_to_4只是這個函數對象的一個引用。先在全局命名空間中刪除generate_power_func
,再試試會出現什么結果。

>>> del generate_power_func
>>> raised_to_4(2)
16

啊哈,居然沒出現錯誤,nth_power是怎么知道n的值是4,而且現在generate_power_func甚至都不在這個命名空間了。對,這就是閉包的作用,外部函數的局部變量可以被內部函數引用,即使外部函數已經返回了。

__closure__ 屬性和 cell 對象

Python中函數也是對象,所以函數也有很多屬性,和閉包相關的就是__closure__ 屬性。
__closure__ 屬性定義的是一個包含 cell 對象的元組,其中元組中的每一個 cell 對象用來保存作用域中變量的值。

>>> raised_to_4.__closure__
(<cell at 0x2bf4ec0: int object at 0x246f770>,)
>>> type(raised_to_4.__closure__[0])
<type 'cell'>
>>> raised_to_4.__closure__[0].cell_contents
4

就如剛才所說,在raised_to_4的__closure__
屬性中有外部函數變量n的引用,通過內存地址可以發現,引用的都是同一個n。如果沒用形成閉包,則__closure__ 屬性為None。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 作用域 在理解閉包前,先看一個函數: 可以看到func()函數內部的變量無法在函數外部使用 全局變量out_fun...
    XYZeroing閱讀 938評論 0 10
  • 我在博客中曾經介紹過兩篇關于函數的文章,第一篇是 關于 Python 函數是第一類對象,第二篇是關于 Lambda...
    liuzhijun閱讀 1,541評論 2 27
  • 一、python函數作用域LEGB python解釋器查找變量的原則(順序):L→E→G→BL:Local函數內部...
    風蕭雨霖閱讀 466評論 0 0
  • 閉包(closure)是函數式編程的重要的語法結構。函數式編程是一種編程范式 (而面向過程編程和面向對象編程也都是...
    Mr_Chen閱讀 320評論 0 1
  • “汪汪”“汪汪”“汪汪” “summer,不要再叫了,剛五點好嘛” “汪汪”“汪汪” ‘咚,咚’閉著眼睛踹了兩腳“...
    Maggie昔年閱讀 385評論 1 1