今天來看看如何用python的Functional Programming tool來簡化程式碼
所謂的Functional Programming, 是指像是Lisp或Haskell這樣的程式語言
python所提供的Functional Programming tool
可以用Functional Programming這些語言的風格來寫python
1. lambda
lambda這個詞是來自於Lambda Calculus
簡而言之, Lambda Calculus是一種計算理論
若想了解Lambda Calculus是什麼, 請看:http://en.wikipedia.org/wiki/Lambda_calculus
而 lambda 這個key word在python裡面是用來定義anonymous functions或small function
例如:
>>> my_function = lambda x : x+2
>>> print my_function(1)
3
或:
>>> print (lambda x : x+2 ) (1)
3
2. map
假設有一個function和一個list,如下:
>>> my_function = lambda x : x+3
>>> my_list = [1,2,3,4,5]
如果要把 my_list
中的每個element用 my_function
做運算
例如:
>>> my_list_2 = []
>>> for x in my_list:
... my_list_2.append(my_function(x))
>>> print my_list_2
[4, 5, 6, 7, 8]
這可以用map改成這樣:
>>> my_list_2 = map(my_function,my_list)
>>> print my_list_2
[4, 5, 6, 7, 8]
也可以直接這樣寫
>>> my_list_2 = map(lambda x : x+3,[1,2,3,4,5])
>>> print my_list_2
[4, 5, 6, 7, 8]
這樣都可以把for迴圈化簡掉
map也可以用於多個argument的function
例如:
>>> print map(lambda x,y : x*y ,[1,2,3,4], [2,4,6,8])
[2, 8, 18, 32]
3.filter
給定一個list如下
>>> my_list = [1,2,3,4,5,6,7,8]
假如要取出 my_list
中為偶數的數字,如下:
>>> my_list_2 = []
>>> for x in my_list:
... if x%2 == 0:
... my_list_2.append(x)
>>> print my_list_2
[2, 4, 6, 8]
filter的概念就是去掉function運算後為False的element,如下:
>>> my_list_2 = filter(lambda x : x%2 == 0, my_list)
>>> print my_list_2
[2, 4, 6, 8]
這樣就可以省略掉for和if,把成式碼合併到一行之中
再一例子,如果要把 my_list
中偶數的element取出來後平方,可以這樣寫:
>>> my_list_2 = filter(lambda x : x**2 if x%2==0 else False, my_list)
>>> print my_list_2
[2, 4, 6, 8]
4.reduce
給定一個list如下
>>> my_list = [3,2,1,6,5,4]
如果要算出這個例子的總和,用for迴圈會這樣寫
>>> sum=0
>>> for x in my_list:
... sum+=x
>>> print sum
21
這樣至少要寫三行,如果用reduce的話一行就夠了
>>> sum = reduce(lambda a,b:a+b,my_list)
>>> print sum
21
reduce的概念如下,用這個function把list中前兩個合併成一個
一直這樣合併下去
以下是reduce的分解過程
把程式碼複製後貼到 my_reduce.py 檔案
def my_reduce(my_fun,my_list):
print my_list
if len(my_list) == 1:
return my_list[0]
elif len(my_list) >= 2:
my_list_1 = my_fun(my_list[0], my_list[1])
return my_reduce(my_fun, [my_list_1] + my_list[2:])
else:
print "Error: reduce of empty sequence"
return False
到interactive mode 執行看看
>>> from my_reduce import *
>>> my_reduce(lambda a,b:a+b,my_list)
[3, 2, 1, 6, 5, 4]
[5, 1, 6, 5, 4]
[6, 6, 5, 4]
[12, 5, 4]
[17, 4]
[21]
21
看到了list前面兩個被function合併成一個,這樣繼續合併下去,得出結果
再舉一例,
如果要求出my_list中的最大值, 可以這樣:
>>> max = reduce(lambda a,b: a if a>=b else b, my_list)
>>> print max
6
分解過程如下:
>>> my_reduce(lambda a,b: a if a>=b else b,my_list)
[3, 2, 1, 6, 5, 4]
[3, 1, 6, 5, 4]
[3, 6, 5, 4]
[6, 5, 4]
[6, 4]
[6]
6
5.Further reading:
想要看更多關於lambda,map,filter和reduce的用法,請到:
http://www.python-course.eu/lambda.php
http://docs.python.org/2/tutorial/datastructures.html#functional-programming-tools