函數不僅可以作為函數參數,還可以作為函數返回結果
def pro1(c,f): def pro2(): return f(c) return pro2
#調用pro1函數時,返回的是pro2函數對象
>>>a = pro1(-3,abs)
#需要對a調用才能得到結果
>>>a()
3
如果在一個內部函數里對外部作用域(但不是全局作用域)的變量進行引用,內部函數稱為閉包(closure)
import math def fun1(n): def fun2(x): return pow(x,n) return fun2 pow2 = fun1(2) print(pow2(9))
#函數fun2對fun1的參數n進行了引用,將帶參數的fun1給一個新的函數pow2
當fun1的生命周期結束時,已經引用的變量n存在在fun2中,依然可以調用
#用閉包實現一個點與點之間的距離計算 def point(x, y): def get_distance(u, v): return sqrt((x - u) ** 2 + (y - v) ** 2) return get_distance >>> pt = point(7, 2) >>> pt(10, 6) 5.0
再看一個廖老師的例子
def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f3 = count()
如果你認為f1,f2,f3三個不同的函數分別返回1,4,9。那就錯了
因為返回函數使用了循環變量i,但是並沒有立刻執行 等到函數全部返回后,i已經是3,得到的結果全部是9
因此,我們應盡量避免在閉包中引用循環變量,或者后續會發生變化的變量。
如果需要引用循環變量,增加一個函數,並且使用該函數的參數綁定循環變量當前的值。
def count(): fs = [] for i in range(1,4): def g(a): #定義一個g函數,參數為a,返回函數f的返回值被綁定 f = lambda : a*a return f fs.append(g(i)) return fs f1,f2,f3 =count() print(f1()) print(f2()) print(f3())
1
4
9
匿名函數
所謂匿名就是不需要函數表達式
lambda x : x*x
關鍵字lambda
表示匿名函數,冒號前面的x
表示函數參數。
匿名函數有個限制,就是只能有一個表達式,不用寫return
,返回值就是該表達式的結果。
#定義一個函數f,參數為a 返回a的平方
這里將匿名函數賦值給變量f
f = lambda a: a*a >>>f(3) 9