python的函數式編程機制
每每看到別人用函數式編程的時候,就覺得別人好膩害,想找個時間自己也去學會這種編程方式,可是呢?一直拖一直拖,今天就把這個技能給收了吧。
那麼什麼是函數式編程呢?
函數式編程使用一系列的函數解決問題。函數僅接受輸入併產生輸出,不包含任何能影響產生輸出的內部狀態。任何情況下,使用相同的參數調用函數始終能產生同樣的結果。
在一個函數式的程序中,輸入的數據「流過」一系列的函數,每一個函數根據它的輸入產生輸出。函數式風格避免編寫有「邊界效應」(side effects)的函數:修改內部狀態,或者是其他無法反應在輸出上的變化。完全沒有邊界效應的函數被稱為「純函數式的」(purely functional)。避免邊界效應意味著不使用在程序運行時可變的數據結構,輸出只依賴於輸入。
可以認為函數式編程剛好站在了面向對象編程的對立面。對象通常包含內部狀態(欄位),和許多能修改這些狀態的函數,程序則由不斷修改狀態構成;函數式編程則極力避免狀態改動,並通過在函數間傳遞數據流進行工作。但這並不是說無法同時使用函數式編程和面向對象編程,事實上,複雜的系統一般會採用面向對象技術建模,但混合使用函數式風格還能讓你額外享受函數式風格的優點。
為什麼使用函數式編程??函數式的風格通常被認為有如下優點:
- 邏輯可證
這是一個學術上的優點:沒有邊界效應使得更容易從邏輯上證明程序是正確的(而不是通過測試)。
- 模塊化 函數式編程推崇簡單原則,一個函數只做一件事情,將大的功能拆分成儘可能小的模塊。小的函數更易於閱讀和檢查錯誤。
- 組件化 小的函數更容易加以組合形成新的功能。
- 易於調試 細化的、定義清晰的函數使得調試更加簡單。當程序不正常運行時,每一個函數都是檢查數據是否正確的介面,能更快速地排除沒有問題的代碼,定位到出現問題的地方。
- 易於測試 不依賴於系統狀態的函數無須在測試前構造測試樁,使得編寫單元測試更加容易。
- 更高的生產率
函數式編程產生的代碼比其他技術更少(往往是其他技術的一半左右),並且更容易閱讀和維護。
那麼說我們的主角python,python不是,也不大可能會成為一種函數式編程語言,但是它支持許多有價值的函數式編程語言的構建,也有些表現得像是函數式編程機制但是從傳統上也不能被認為是函數式編程語言的構建。python以四種內建函數和lambda表達式的形式出現:map、reduce 、filter、sorted 、和lambda表達式。
下面一一介紹用法:
map:我們在使用map函數時候,map函數需要接收兩個參數,第一個參數是函數,第二個參數是序列,那麼表示的含義就是map將傳入的函數依次作用在序列中的每一個元素,並把結果以列表的形式返回。
def f(x):n return x*xnprint map(f,[1,2,3,4,5,6,7,8,9,10])n
結果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]n
reduce:reduce函數和map函數有什麼不同之處呢?reduce函數也需要兩個參數:函數和序列。reduce參數中的函數必須接收兩個參數,那麼reduce函數表示的含義則為把返回的結果繼續和序列的下一個元素做累積計算,典型例子比如對序列求和。
def f2(x,y):n print x,yn return x+y n nprint reduce(f2,[1,2,3,4,5,6,7,8,9,10])n
結果:
1 2n3 3n6 4n10 5n15 6n21 7n28 8n36 9n45 10n55n
filter:filter函數用於過濾序列中某些元素。和map、reduce函數一樣,filter也接收一個函數和一個序列,不同的是,filter把傳入的函數參數作用於序列中每一個元素,然後根據返回值判斷是true還是false來決定該元素是否被丟棄。
def isEven(x):n return x%2==0n nprint filter(isEven,[1,2,3,4,5,6,7,8,9,10])n
結果:
[2, 4, 6, 8, 10]n
sorted:排序功能強大。
def cmp_value(x,y): n if x > y : n return 1 n elif x < y: n return -1 n else: n return 0 nso = sorted(this is a string.split( ),cmp=cmp_value) nprint so n
結果:
[a, is, string, this]n
lambda:便利強大的lambda函數又稱為匿名函數,它不需要顯式的定義函數,但是匿名函數也有一些限制,就是只能有一個表達式,不用寫return,返回值就是該表達式的結果。
匿名函數也是有很多優點的,要不然怎麼會使用它呢。第一,函數沒有名字,不必擔心有函數名衝突;第二,匿名函數是一個函數對象,也可以把匿名函數賦值給一個變數,然後利用變數來調用函數。
print map(lambda x : x*x , [1,2,3,4,5,6,7,8,9,10])nff = lambda x : x*x*x nprint ff(5)n
結果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]n125n
那麼就基本上,python的函數式編程,以後就可以參照上面的形式進行編寫了,可能遇到複雜的問題,還需要深入一下,再說吧,先把學會簡單的使用方式。
今天就先到這裡,晚安。
參考資料:
1.python核心編程(第二版)。
2.Python學習總結之五 -- 入門函數式編程.
3.Python函數式編程指南(一):概述 - AstralWind - 博客園
推薦閱讀:
※Python從零開始系列連載(13)——Python程序的基本控制流程(上)
※使用Flask開發簡單博客的教程(上)
※Python入門到精通視頻課程(2)
※給妹子講python--01好用的列表
TAG:Python教程 |