1、函數做爲返回值數組
高階函數除了能夠接受函數做爲參數外,還能夠把函數做爲結果值返回。閉包
1 >>> def lazy_sum(*args): 2 ... def sum(): 3 ... ax = 0 4 ... for n in args: 5 ... ax = ax + n 6 ... return ax 7 ... return sum 8 ... 9 >>> f = lazy_sum(1, 3, 5, 7, 9) 10 >>> f 11 <function lazy_sum.<locals>.sum at 0x1014ae730> 12 >>> f() 13 25
當咱們調用lazy_sum()
時,每次調用都會返回一個新的函數,即便傳入相同的參數:app
1 >>> f1 = lazy_sum(1, 3, 5, 7) 2 >>> f2 = lazy_sum(1, 3, 5, 7) 3 >>> f1 4 <function lazy_sum.<locals>.sum at 0x1014ae8c8> 5 >>> f2 6 <function lazy_sum.<locals>.sum at 0x1014ae7b8> 7 >>> f1 == f2 8 False
2、閉包函數
在計算機科學中,閉包(Closure)是詞法閉包(Lexical Closure)的簡稱,是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即便已經離開了創造它的環境也不例外。因此,有另外一種說法認爲閉包是由函數和與其相關的引用環境組合而成的實體。閉包在運行時能夠有多個實例,不一樣的引用環境和相同的函數組合能夠產生不一樣的實例。spa
簡單的說,這種內部函數可使用外部函數變量的行爲,就叫閉包。code
在這個例子中,咱們在函數lazy_sum
中又定義了函數sum
,而且,內部函數sum
能夠引用外部函數lazy_sum
的參數和局部變量,當lazy_sum
返回函數sum
時,相關參數和變量都保存在返回的函數中,這種稱爲「閉包(Closure)」的程序結構擁有極大的威力。blog
注意到返回的函數在其定義內部引用了局部變量args
,因此,當一個函數返回了一個函數後,其內部的局部變量還被新函數引用,因此,閉包用起來簡單,實現起來可不容易。io
返回閉包時牢記一點:返回函數不要引用任何循環變量,或者後續會發生變化的變量。function
1 >>> def count(): 2 ... fs = [] 3 ... for i in range(1, 4): 4 ... def f(): 5 ... return i * i 6 ... fs.append(f) 7 ... return fs 8 ... 9 >>> f1, f2, f3 = count() 10 >>> f1() 11 9 12 >>> f2() 13 9 14 >>> f3() 15 9
所有都是9
!緣由就在於返回的函數引用了循環變量i
,但它並不是馬上執行。等到3個函數都返回時,它們所引用的變量i
已經變成了3
,所以最終結果爲9
。class
若是必定要引用循環變量怎麼辦?方法是再建立一個函數,用該函數的參數綁定循環變量當前的值,不管該循環變量後續如何更改,已綁定到函數參數的值不變:
1 >>> def count(): 2 ... def f(j): 3 ... def g(): 4 ... return j * j 5 ... return g 6 ... fs = [] 7 ... for i in range(1, 4): 8 ... fs.append(f(i)) 9 ... return fs 10 ... 11 >>> f1, f2, f3 = count() 12 >>> f1() 13 1 14 >>> f2() 15 4 16 >>> f3() 17 9