Python閉包Closure 2

  因爲Python中,變量做用域爲LEGB,因此在函數內部能夠讀取外部變量,可是在函數外不能讀取函數內的變量。可是出於種種緣由,咱們須要讀取函數內的變量時候怎麼辦?那就是在函數內在加一個函數。javascript

1 def outer():
2     x = 5
3     def inner():
4         print(x)
5     return inner
6 
7 a = outer()
8 a()#print 5

這樣,咱們就能夠看到函數內部的變量了。html

上面的inner就是閉包,閉包就是可以讀取其餘函數內部變量的函數,也就是定義在函數內部的函數,在本質上來講,閉包就是鏈接函數內和函數外的橋樑。同時,閉包也能夠理解爲能夠攜帶狀態的函數,能夠用這個特性構建相似於類private變量,攜帶狀態的回調函數等。java

 

閉包有兩大做用,一個是像上面的能夠讀取函數內部的變量,一個是讓這些變量的值始終保存在內存中。閉包

 1 def outer():
 2     n = 999
 3     def tr():
 4         nonlocal n
 5         n = n+1
 6     def inner():
 7         print(n)
 8     return tr,inner
 9 
10 tr,a = outer()
11 a()#print999
12 tr()
13 a()#print1000

由於outer爲inner的父函數,而inner被賦值給了一個全局變量,這致使inner和inner依賴的outer常駐內存app

 

須要注意的是,返回的函數並無立馬執行,直到調用時候纔開始執行。函數

def outer():
    acts = []
    for i in range(5):
        acts.append(lambda x:i**x)
    return acts

acts = outer()
for i in range(5):
    print(acts[i](2))
#print
#16
#16
#16
#16
#16

 

輸出爲五個16而不是咱們想要的結果,爲何?性能

就是由於act[i]在內存中一直沒有執行,一直等到調用纔開始執行的,那怎麼辦?學習

方法就是用函數的參數綁定循環變量的值,這樣不管循環變量的值怎麼改變,已經綁定到函數參數的值不會改變spa

 1 def outer():
 2     acts = []
 3     for i in range(5):
 4         acts.append(lambda x,i=i:i**x)
 5     return acts
 6 
 7 acts = outer()
 8 for i in range(5):
 9     print(acts[i](2))
10 #print
11 #0
12 #1
13 #4
14 #9
15 #16

 

 

使用閉包時候要注意:3d

1)因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露。解決方法是,在退出函數以前,將不使用的局部變量所有刪除。

2)閉包會在父函數外部,改變父函數內部變量的值。因此,若是你把父函數看成對象(object)使用,把閉包看成它的公用方法(Public Method),把內部變量看成它的私有屬性(private value),這時必定要當心,不要隨便改變父函數內部變量的值。

 

參考資料:學習javascript閉包

      Javascript閉包

     Python學習手冊p431

     Python Cookbook

相關文章
相關標籤/搜索