函數語言程式設計(英語:functional programming)或稱函式程式設計,又稱泛函程式設計,是一種程式設計範型,它將電腦運算視為數學上的函式計算,並且避免使用程式狀態以及易變物件。函式程式語言最重要的基礎是λ演算(lambda calculus)。而且λ演算的函式可以接受函式當作輸入(引數)和輸出(傳出值)。(維基百科:函數語言程式設計)
所謂程式設計正規化(Programming paradigm)是指程式設計風格、方法或模式,比如程式導向程式設計(C語言)、物件導向程式設計(C++)、面向函數語言程式設計(Haskell),並不是說某種程式語言一定屬於某種正規化,例如 Python 就是多正規化程式語言。
函數語言程式設計
函數語言程式設計具有以下特點:
- 避免狀態變數
- 函式也是變數(一等公民,First-Class Citizen)
- 高階函式
- 面向問題描述而不是面向問題解決步驟
值得一提的是,函數語言程式設計的這些特點在實踐過程中可能並不是那麼 Pythonic,甚至與0x00中提到的 The Zen of Python 相悖。例如函數語言程式設計面向問題描述的特點可能讓你更快地寫出更簡潔的程式碼,但可讀性卻也大打折扣(可參考這一段Haskell程式碼)。不過,雖然 Pythonic 很重要但並不是唯一的準則,The Choice Is Yours。
map(function, iterable, ...)
/filter(function, iterable)
1 2 3 4 5 6 7 8 9 10 |
# map 函式的模擬實現 def myMap(func, iterable): for arg in iterable: yield func(arg) names = ["ana", "bob", "dogge"] print(map(lambda x: x.capitalize(), names)) # Python 2.7 中直接返回列表 for name in myMap(lambda x: x.capitalize(), names): print(name) |
1 2 3 |
Ana Bob Dogge |
1 2 3 4 5 6 7 8 9 |
# filter 函式的模擬實現 def myFilter(func, iterable): for arg in iterable: if func(arg): yield arg print(filter(lambda x: x % 2 == 0, range(10))) # Python 2.7 中直接返回列表 for i in myFilter(lambda x: x % 2 == 0, range(10)): print(i) |
1 2 3 4 5 |
0 2 4 6 8 |
functools.reduce(function, iterable[, initializer])
Python 3.5 中reduce
被降格到標準庫functools
,reduce
也是遍歷可迭代物件元素作為第一個函式的引數,並將結果累計:
1 2 3 |
from functools import reduce print(reduce(lambda a, b: a*b, range(1,5))) |
1 |
24 |
functools.partial(func, *args, **keywords)
偏應用函式(Partial Application)讓我們可以固定函式的某些引數:
1 2 3 4 5 6 |
from functools import partial add = lambda a, b: a + b add1024 = partial(add, 1024) add1024(1) |
1 |
1025 |
這裡簡單介紹了一些常用函數語言程式設計的方法和概念,實際上要傳達的一個最重要的觀念就是函式本身也可以作為變數被返回、傳遞給高階函式,這使得我們可以更靈活地運用函式解決問題。但是這並不意味著一定要使用上面這些方法來簡化程式碼,例如更 Pythonic 的方法推薦儘可能使用 List Comprehension 替代map
/filter
(關於 List Comprehension 後面會再單獨介紹)。如果一定想要用函數語言程式設計的方法來寫 Python,也可以嘗試Fn.py,或者,試試 Haskell。