引言
Functional Programming(函數語言程式設計)的概念最早起源於LISP,由約翰·麥卡錫在1958年創立,最早提出了自動垃圾回收的理念,這一理念現在也被Python/Java/Ruby等多種語言借鑑。發展到今天,LISP已經衍生出了多種方言。相比物件導向程式設計,函數語言程式設計的一大優勢就是Immutable Data(資料不可變),就是不依賴於外部的資料,而且也不改變外部資料的值,這種思想可以大大減少我們程式碼的Bug,而且函數語言程式設計也支援我們像使用變數一樣使用函式。Python作為面嚮物件語言,也提供了對於函數語言程式設計的支援,雖然並不是那麼純粹,而且也不支援尾遞迴優化。
lambda的使用
lambda即匿名函式,合理地使用lambda不僅可以減少我們的程式碼量,而且也可以更好地描繪程式碼邏輯,比如現在我們有下面這樣一個函式。
1 2 3 4 5 |
>>> def f(x): ... return x + x # 呼叫這個函式 >>> f(2) 4 |
這個函式如果我們用lamda改寫的話,只要一行程式碼就夠了。
1 2 3 4 5 6 7 8 |
# lambda後面的x表示lambda函式要接收的引數,x + x表示lambda函式所要返回的值 >>> f = lambda x: x + x # 可以看到f現在也是一個函式物件 >>> f <function __main__.<lambda>> # 呼叫lambda函式 >>> f(2) 4 |
map的使用
map(function, iterable)接收兩個引數,第一個引數代表的是接收一個函式,第二個引數代表的是接收一個iteralbe型別的物件,比如list。
map函式的原理是: 1.每次從iterable中取出一個引數,2.將這個引數傳遞給我們的函式,3.然後函式返回的值加入一個list(這種說法不準確,只是為了幫助大家理解,後面我會解釋)。等所有的iterable物件遍歷完,map就把這個list返回給我們的呼叫者。下面我們直接通過例項來了解一下map的用法。
example1
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 還是用我們上面那個lambda的例子 >>> function = lambda x: x + x # 定義一個iterable物件list(列表) >>> iterable = [1, 2, 3, 4, 5, 6, 7, 8, 9] # 函式fucntion每次從iterable中取出一個引數x,然後function返回x + x的值, # 並將返回值加入一個新建的list,等將iterable遍歷完,map就將這個新建的list返回。 >>> v = map(function, iterable) # 注意上面的說法並不準確,只是為了幫助大家理解,其實map返回的是一個map物件,並不是list >>> v <map at 0x7fcb56231588> # 但是我們可以呼叫內建的list函式將map轉換成一個list來得到我們想要的結果 >>> list(v) [2, 4, 6, 8, 10, 12, 14, 16, 18] |
example2
對於map的第二個引數,我們也可以傳遞一組函式列表進去,也就是說列表中間包含多個函式物件。
1 2 3 4 5 |
>>> multiply = lambda x: x * x >>> add = lambda x: x + x >>> funcs = [multiply, add] >>> list(map(lambda f: f(1), funcs)) [1, 2] |
reduce的使用
與map一樣,reduce(function, iterable)也接收兩個引數,第一個引數代表的是接收一個函式,第二個引數代表的是接收一個iteralbe型別的物件,比如list。不過不同的地方在於reduce中的這個函式必須要接收兩個引數,下面我們來通過求一個list(列表)累加和的例子來了解一下reduce的用法。
1 2 3 4 5 6 7 8 |
from functools import reduce # 使用lambda定義一個函式,函式的作用是接收兩個引數,然後返回兩個引數之和 >>> function = lambda x, y: x+y >>> iterable = [1, 2, 3, 4, 5, 6, 7, 8, 9] # 函式function每次接收兩個引數,除第一次外每次從iterable中取一個元素作為一個引數 # 另外一個引數取自上一次function返回的值 >>> reduce(function, iterable) 45 |
filter的使用
和map/reduce類似,filter(function, iterable)一次也接收兩個引數,一個引數是函式,另外一個引數是iterable物件,從名字也可以看出,filter用於過濾iterble物件,比如說list(列表)。
它的原理是每次從iterable物件中取出一個元素作用於我們的function,如果function返回True就保留該元素,如果返回False就刪除該元素。下面我們通過一個例項來看一下filter的用法。
1 2 3 4 5 6 7 |
# 定義一個函式,如果接收的字元s為空,那麼返回False,如果為非空,那麼返回True >>> function = lambda s : s and s.strip() >>> iterable = ['AJ', ' ', 'Stussy', '', 'CLOT', 'FCB', None] >>> filter(function, iterable) <filter at 0x7fcb562319b0> >>> list(filter(function, iterable)) ['AJ', 'Stussy', 'CLOT', 'FCB'] |
裝飾器
裝飾器(decorator)是一種高階Python語法。裝飾器可以對一個函式、方法或者類進行加工。合理地使用裝飾器可以減少我們的程式碼量以及提高程式的可讀型,在很多Python框架中,比如Django中我們可以大量看到裝飾器的身影。
1 2 3 4 5 6 |
>>> def add(x, y): ... return x + y ... >>> def multiply(x, y): ... return x * y ... |
現在我們有上面兩個函式,分別用來求加法和乘法,但是現在我們覺得功能不夠,想在返回結果前新增一些輸出語句,一般來說我們要重構兩個函式,就向下面這樣。
1 2 3 4 5 6 7 8 |
>>> def add(x, y): ... print("input:", x, y) ... return x + y ... >>> def multiply(x, y): ... print("input:", x, y) ... return x * y ... |
如果使用裝飾器我們可以像下面這樣做,雖然現在我們這種情形看起來使用裝飾器並沒有什麼優勢,但是如果我們要新增的不止一條列印功能,以及除了add/multiply我們還有minus/divide等函式,這個時候裝飾器的威力就體現出來了,我們只用修改一處程式碼即可,這樣不僅提高了程式的可讀性而且也為以後我們重構程式碼省去了很多的工作量。
1 2 3 4 5 6 7 8 9 10 11 |
def decorator(F): def new_function(x, y): print("input:", x, y) return F(x, y) return new_function @decorator def add(x, y): return x + y @decorator def multiply(x, y): return x * y |