函數式編程即函數可以作為參數傳入函數,也可以返回函數。 1.高階函數 函數可以作為參數傳入函數。 def add(x,y,f): return f(x)+f(y) 調用add函數add(3,-4,abs) ,結果為7 2.map/reduce def f(x): return x*x map(f,[ ...
函數式編程即函數可以作為參數傳入函數,也可以返回函數。
1.高階函數 函數可以作為參數傳入函數。 def add(x,y,f): return f(x)+f(y) 調用add函數add(3,-4,abs) ,結果為7 2.map/reduce def f(x): return x*x map(f,[1,2,3,4,5]) 返回的是一個Iterator,用list()可以把它全部顯示出來。map()的作用即把f函數作用於第二個Iterable參數的每一個元素上。 def add(x,y): return x+y reduce(add,[1,2,3,4,5])返回的同樣也是一個Iterator。 上一個語句就相當於add(add(add(add(1,2),3),4),5).所以reduce()接收的第一個函數參數就只能是接收兩個參數的函數。 map/reduce都是高階函數 3.filter/sorted (1) 以輸出素數為filter()的例子 ①初始數列直接考慮奇數列,除2之外偶數均非素數 def _odd_iter():n=1②排除條件 def _delete(n):
while True:#這是一個生成器,所以不用擔心沒有退出條件的問題
n=n+2
yield n
return lambda x: x % n >0
③輸出素數
def primes():
yield 2 #因為2不在初始奇數列中,所以先輸出2
it=_odd_iter()#初始數列
while True:
n=next(it)
yield n
it = filter(_delete(n),it) #filter()將it中_delete()作用後為False的 #元素都刪除
④限定一個輸出範圍 否則將無限輸出下去
for n in primes():
if n < 1000:
print(n)
else:
break
(2)sorted()
L=[('Bob',75),('Adam',92),('Bart',66),('Lisa',88)]
def by_name(t):
return t[0]
L2=sorted(L,key=by_name) #類似map,key參數接收的函數也是作用於L的每一個元素
#所以這裡返回的就是Bob,Adam,Bart,Lisa,然後再對L的元素排序
#key只是排序依據,不改變L
print(L2)
def by_score(t):
return t[1]
L3=sorted(L,key=by_score)
print(L3)
Output:[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
[('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Adam', 92)]
對於str,sorted()是按ASCII來排序的,所以大寫會排在小寫之前
L=['Credit','about','Zoey','Bart','effect']
print(sorted(L))
OUTPUT:['Bart', 'Credit', 'Zoey', 'about', 'effect']
print(sorted(L,reverse=True)) #reverse參數為反轉
Output:['effect', 'about', 'Zoey', 'Credit', 'Bart']
4.返回函數
高階函數不僅可以接收函數作為參數,還可以返回函數。
當調用函數不需要立刻得到結果,而是想以後的需要的時候再計算結果,可以返回函數。
def lazy_sum(*args):
def sum():
ax=0
for n in args:
ax=ax+n
return ax
return sum
f=lazy_sum(1,2,3,4,5)
當運行之後,lazy_sum返回一個sum函數,賦值給f,lazy_sum()由args的傳入的相關參數和變數也都保存在f中,但還未計算,等到調用時f會使用這些參數並計算。這種現象稱為“閉包”。
因為f是當調用時才計算結果
def count(): fs=[] for i in range(1,4): def f(): return i*i fs.append(f) return fs #因為fs.append(f)中f是一個函數,所以這裡也有返回函數的意思 f1,f2,f3=count() print(f1())#這裡調用時,上面一句3個函數都已經返回了,此時的i已經變成3,所
#以接下來調用f2,f3,它們保存的參數i都為3,所以最後結果都是9
print(f2())
print(f3())
Output:9
9
9
所以返回函數時,返回函數里不要有可能會變化的變數。
5.匿名函數
其實就是一個簡易的函數定義式
如def f(x):
return x*x
寫成匿名函數就lambda x : x*x #冒號左邊的x是參數,右邊是返回式
6.裝飾器(Decorator)
在運行代碼期間動態增加功能,但又不改變函數原來的定義。
import functools
def log(func):
@functools.wraps(func) #相當於wrapper.__name__=func.__name__,如果沒有這一句,運行now.__name__就會得到wrapper,因為log返回的函數是wrapper
def wrapper(*args,**kw):
print('call %s():'%func.__name__) #列印日誌
return func(*args,**kw) #調用函數
return wrapper #所以log(now)即返回wrapper函數,wrapper函數的功能就是先列印日誌,再調用輸入的函數
@log
def now(): #這兩句相當於now=log(now)
print('2016.8.10')
print(now())
Output:
call now():
2016.8.10
7.偏函數
import functools
int2 =functools.partial(int,base=2) #把某個函數的某個參數設一個預設值,生成一個新的函數
print(int2('100000'))
print(int2('12345',base=8)) #這個新的函數任然是可以更改這個參數值的,只是它有一個預設的參數值
Output:
32
5349
其實就相當於
def int2(x,base=2)
return int(x,base)