盡管Python事實上并不是一門純函數(shù)式編程語言,但它本身是一門多范型語言,并給了你足夠的自由利用函數(shù)式編程的便利。函數(shù)式風格有著各種理論與實際上的好處(你可以在Python的文檔中找到這個列表):
形式上可證 模塊性 組合性 易于調(diào)試及測試雖然這份列表已經(jīng)描述得夠清楚了,但我還是很喜歡Michael O.Church在他的文章“函數(shù)式程序極少腐壞(Functional programs rarely rot)”中對函數(shù)式編程的優(yōu)點所作的描述。我在PyCon UA 2012期間的講座“Functional Programming with Python”中談論了在Python中使用函數(shù)式方式的內(nèi)容。我也提到,在你嘗試在Python中編寫可讀同時又可維護的函數(shù)式代碼時,你會很快發(fā)現(xiàn)諸多問題。
fn.py類庫就是為了應對這些問題而誕生的。盡管它不可能解決所有問題,但對于希望從函數(shù)式編程方式中獲取最大價值的開發(fā)者而言,它是一塊“電池”,即使是在命令式方式占主導地位的程序中,也能夠發(fā)揮作用。那么,它里面都有些什么呢?
Scala風格的Lambda定義
在Python中創(chuàng)建Lambda函數(shù)的語法非常冗長,來比較一下:
Python
map(lambda x: x*2, [1,2,3])
Scala
代碼如下:
List(1,2,3).map(_*2)
Clojure
代碼如下:
(map #(* % 2) '(1 2 3))
Haskell
代碼如下:
map (2*) [1,2,3]
受Scala的啟發(fā),F(xiàn)n.py提供了一個特別的_對象以簡化Lambda語法。
from fn import _assert (_ + _)(10, 5) = 15assert list(map(_ * 2, range(5))) == [0,2,4,6,8]assert list(filter(_ < 10, [9,10,11])) == [9]
除此之外還有許多場景可以使用_:所有的算術操作、屬性解析、方法調(diào)用及分片算法。如果你不確定你的函數(shù)具體會做些什么,你可以將結果打印出來:
from fn import _ print (_ + 2) # "(x1) => (x1 + 2)" print (_ + _ * _) # "(x1, x2, x3) => (x1 + (x2 * x3))"
流(Stream)及無限序列的聲明
Scala風格的惰性求值(Lazy-evaluated)流。其基本思路是:對每個新元素“按需”取值,并在所創(chuàng)建的全部迭代中共享計算出的元素值。Stream對象支持<<操作符,代表在需要時將新元素推入其中。
惰性求值流對無限序列的處理是一個強大的抽象。我們來看看在函數(shù)式編程語言中如何計算一個斐波那契序列。
Haskell
代碼如下:fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Clojure
代碼如下:(def fib (lazy-cat [0 1] (map + fib (rest fib))))
Scala
代碼如下:def fibs: Stream[Int] =
0 #:: 1 #:: fibs.zip(fibs.tail).map{case (a,b) => a + b}
現(xiàn)在你可以在Python中使用同樣的方式了:
新聞熱點
疑難解答