函數(shù)式編程
簡介:一種編程范式
- 把計算視為函數(shù)而非指令
- 純函數(shù)式編程:不需要變量匆背,沒有副作用剧包,測試簡單
- 支持高階函數(shù)核偿,代碼簡單
高階函數(shù):
能接收函數(shù)做參數(shù)的函數(shù)
- 變量可以指向函數(shù)
- 函數(shù)的參數(shù)可以接收變量
- 一個函數(shù)可以接收另一個函數(shù)作為參數(shù)
- 能接收函數(shù)作為參數(shù)的函數(shù)被稱為高階函數(shù)
eg1:
def add(x,y,f):
return f(x)+f(y)
print add(0,4,math.sqrt) #注意不是math.sqrt()
eg2:
def format_name(s):
return s[0].upper()+s[1:].lower()
print map(format_name, ['adam', 'LISA', 'barT'])
eg3:
def is_sqr(x):
if int(math.sqrt(x)) == math.sqrt(x):
return x
print filter(is_sqr, range(1, 101))
python 中返回函數(shù)(一個函數(shù)執(zhí)行的結(jié)果是返回另一個函數(shù))
eg:1
def calc_sum(lst):
def lazy_sum():
return sum(lst)
return lazy_sum
使用f的時候并沒有調(diào)用它(延遲求值)
>>> f = calc_sum([1, 2, 3, 4])
>>> f
<function lazy_sum at 0x1037bfaa0>
>>> f()
10
eg2:
def calc_prod(lst):
def lazy_prod():
def prod(x,y):
return x*y
return reduce(prod,lst)
return lazy_prod
f = calc_prod([1, 2, 3, 4])
print f()
python閉包:
概念:內(nèi)層函數(shù)引用了外層函數(shù)的變量(參數(shù)也算變量)迹缀,然后返回內(nèi)層函數(shù)的情況瓦糕,稱為閉包(Closure)胁艰。(如上calc_prod函數(shù)中款筑,內(nèi)部的reduce函數(shù)引用了 外部的lst變量)
閉包的特點是返回的函數(shù)還引用了外層函數(shù)的局部變量,所以腾么,要正確使用閉包奈梳,就要確保引用的局部變量在函數(shù)返回后不能變。
eg1:
def count():
fs =[]
for i in range(1,4):
def f():
return i*i
fs.append(f)
return fs
f1,f2,f3 =count()
print(f1(),f2(),f3())
結(jié)果不是1解虱,4攘须,9 而是9,9殴泰,9于宙,因為return的時候fs里面三個函數(shù)都沒有執(zhí)行,參數(shù)都是i悍汛,在調(diào)用的時候才開始執(zhí)行捞魁,而此時i已經(jīng)變成的。因此离咐,返回函數(shù)不要引用任何循環(huán)變量谱俭,或者后續(xù)會發(fā)生變化的變量。(take this sentence in mind)
注意:python函數(shù)加不加括號問題
1宵蛀、不帶括號時昆著,調(diào)用的是這個函數(shù)本身 (比如上面函數(shù)式編程)
2、帶括號(此時必須傳入需要的參數(shù))糖埋,調(diào)用的是函數(shù)的return結(jié)果(加括號就是調(diào)用了)
python匿名函數(shù):
利用lambda表達(dá)匿名返回值而不是return
def is_not_empty(s):
return s and len(s.strip()) > 0
化簡為:
print filter(lambda s: s and len(s.strip())>0, ['test', None, '', 'str', ' ', 'END'])
python裝飾器decorator
接收 一個函數(shù)對其包裝然后返回一個新函數(shù)宣吱,用于對原函數(shù)功能進(jìn)行增加又不想修改原函數(shù)的代碼
def f1(x):
return x*2
def newf(f):
def fn(x):
print('new functions')
return f(x)
return fn
使用方法
g1 = newf(f1)
print g1(5)
or
f1 = new_fn(f1)
print f1(5)
這樣就徹底隱藏了f1函數(shù)
python內(nèi)置的@語法用來簡化裝飾器的調(diào)用
@newf
def f1(x)
return x*2
等價于
def f1(x):
return x*2
f1 =newf(f1)
即把f1包含在了newf里面并返回一個函數(shù)名還是f1的新的函數(shù),因而在調(diào)用f1時瞳别,原來的newf也同時被執(zhí)行了征候。想想@log就能明白了杭攻,執(zhí)行@log下面的函數(shù)時,log也被打印出來疤坝,而新函數(shù)的函數(shù)名還是@log下面的函數(shù)名
def log1(f):
print("print log")
return f
@log1
def d(x):
print(x)
output
print log
1
把d(x)變成了
def d(x):
print("print log")
print(x)
裝飾器模塊后續(xù)更新: