1. 閉包
形式:函數(shù)作為返回值请琳,高階函數(shù)除了可以接受函數(shù)作為參數(shù)外,還可以把函數(shù)作為結(jié)果值返回。
def calc_sum(lst):
def lazy_sum():
return sum(lst)
return lazy_sum
f = calc_sum() //不會調(diào)用
f()
這里的calc_sum
可以進(jìn)行字面理解為“懶求和”
當(dāng)函數(shù)f
定義好了以后围苫,實(shí)際上是定義了一個函數(shù)的實(shí)體。只有在f()
進(jìn)行調(diào)用以后才進(jìn)行了函數(shù)求和的功能撤师。
閉包中有局部變量剂府。
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
上述中的程序返回看似返回的結(jié)果是1, 4, 9。
而實(shí)際結(jié)果全部都為16剃盾。
這從閉包的特性上也可以理解腺占。我們定義了一個函數(shù)的實(shí)體,在其f1()痒谴,f2(), f3()調(diào)用以后才進(jìn)行了輸出衰伯。這里他們都是單獨(dú)的函數(shù)實(shí)體,內(nèi)部的值互不影響积蔚。
2. 匿名函數(shù)(lambda)
當(dāng)我們在傳入函數(shù)時(shí)意鲸,有些時(shí)候,不需要顯式地定義函數(shù)尽爆,直接傳入匿名函數(shù)更方便怎顾。
例如我們使用一行代碼就能打印出來1,20中所有的奇數(shù)漱贱。
print(list(filter(lambda x : x % 2 == 1, range(1, 20))))
找出一組數(shù)據(jù)中的非空數(shù)據(jù)槐雾。
print filter(lambda s: s and len(s.strip()) > 0, ['test', None, '', 'str', ' ', 'END'])
由上述的例子可以看出lambda極大的減少了代碼量。
3. 裝飾器(decorator)
Python的decorator 本質(zhì)上就是一個高階函數(shù)幅狮,它接收一個函數(shù)作為參數(shù)募强,然后株灸,返回一個新函數(shù)。
import time
def performance(f):
def log_time(x):
t1= time.time()
res = f(x)
t2=time.time()
print 'call %s() in %fs' % (f.__name__, (t2 - t1))
return res
return log_time
@performance
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
call factorial() in 0.002492s
3628800
@performance
在python中就是調(diào)用這個裝飾器的關(guān)鍵字钻注。在Java中也由類似的操作蚂且,Java中稱之為注解。
當(dāng)然這種高階函數(shù)中也可以傳入?yún)?shù)幅恋,當(dāng)我們在做不通的裝飾器時(shí)杏死,返回不同的功能,最常用的就是各種logger
utl了捆交。
import time
def performance(unit):
def performace_docorator(f):
def log_time(*args, **kwargs):
start_time = time.time()
res = f(*args, **kwargs)
end_time = time.time()
print("call %s() in %f%s" % (f.__name__, end_time - start_time, unit))
return res
return log_time
return performace_docorator
@performance('ms')
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
call factorial() in 0.002869ms
3628800
4.偏函數(shù)
當(dāng)一個函數(shù)有很多參數(shù)時(shí)淑翼,調(diào)用者就需要提供多個參數(shù)。如果減少參數(shù)個數(shù)品追,就可以簡化調(diào)用者的負(fù)擔(dān)玄括。
比如,int()函數(shù)可以把字符串轉(zhuǎn)換為整數(shù)肉瓦,當(dāng)僅傳入字符串時(shí)遭京,int()函數(shù)默認(rèn)按十進(jìn)制轉(zhuǎn)換,但int()函數(shù)還提供額外的base參數(shù)泞莉,默認(rèn)值為10哪雕。如果傳入base參數(shù),就可以做 N 進(jìn)制的轉(zhuǎn)換:
functools.partial就是幫助我們創(chuàng)建一個偏函數(shù)的鲫趁,不需要我們自己定義int2()斯嚎,可以直接使用下面的代碼創(chuàng)建一個新的函數(shù)int2:
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85