python學習(四):函數式編程

面向過程 vs 函數式

       函數是Python內建支持的一種封裝,我們通過把大段代碼拆成函數,通過一層一層的函數調用,就可以把複雜任務分解成簡單的任務,這種分解可以稱之爲面向過程的程序設計。函數就是面向過程的程序設計的基本單元。而函數式編程(請注意多了一個“式”字)—Functional Programming,雖然也可以歸結到面向過程的程序設計,但其思想更接近數學計算。
       函數式編程就是一種抽象程度很高的編程範式,純粹的函數式編程語言編寫的函數沒有變量,因此,任意一個函數,只要輸入是確定的,輸出就是確定的,這種純函數我們稱之爲沒有副作用。而允許使用變量的程序設計語言,由於函數內部的變量狀態不確定,同樣的輸入,可能得到不同的輸出,因此,這種函數是有副作用的。函數式編程的一個特點就是,允許把函數本身作爲參數傳入另一個函數,還允許返回一個函數!
       Python對函數式編程提供部分支持。由於Python允許使用變量,因此,Python不是純函數式編程語言。

計算機 vs 計算

       在計算機的層次上,CPU執行的是加減乘除的指令代碼,以及各種條件判斷和跳轉指令,所以,彙編語言是最貼近計算機的語言。而計算則指數學意義上的計算,越是抽象的計算,離計算機硬件越遠。對應到編程語言,就是越低級的語言,越貼近計算機,抽象程度低,執行效率高,比如C語言;越高級的語言,越貼近計算,抽象程度高,執行效率低,比如Lisp語言。

變量 vs 函數名

函數本身也可以賦值給變量,即:變量可以指向函數。那麼函數名是什麼呢?函數名其實就是指向函數的變量。

高階函數

既然變量可以指向函數,函數的參數能接收變量,那麼一個函數就可以接收另一個函數作爲參數,這種函數就稱之爲高階函數。函數式編程就是指這種高度抽象的編程範式。
1. map:該函數接收兩個參數,一個是函數,一個是Iterable,map將傳入的函數依次作用到序列的每個元素,並把結果作爲新的Iterator返回
2. reduce把一個函數作用在一個序列[x1, x2, x3, …]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4).
3.filter:Python內建的filter()函數用於過濾序列。和map()類似,filter()也接收一個函數和一個序列。和map()不同的時,filter()把傳入的函數依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素。可見用filter()這個高階函數,關鍵在於正確實現一個“篩選”函數。
4. sorted:排序也是在程序中經常用到的算法。無論使用冒泡排序還是快速排序,排序的核心是比較兩個元素的大小。如果是數字,我們可以直接比較,但如果是字符串或者兩個dict呢?直接比較數學上的大小是沒有意義的,因此,比較的過程必須通過函數抽象出來。sorted()函數也是一個高階函數,它還可以接收一個key函數來實現自定義的排序。key指定的函數將作用於list的每一個元素上,並根據key函數返回的結果進行排序。要進行反向排序,不必改動key函數,可以傳入第三個參數reverse=True。用sorted()排序的關鍵在於實現一個映射函數。


返回函數與閉包

高階函數除了可以接受函數作爲參數外,還可以把函數作爲結果值返回;
返回一個函數時,牢記該函數並未執行,返回函數中不要引用任何可能會變化的變量。
python閉包(closure):其實並不是什麼很複雜的東西通俗的講就是,如果在一個內部函數裏,對在外部作用域(但不是在全局作用域)的變量進行引用,那麼內部函數就被認爲是閉包(closure)。它只不過是個“內層”的函數,由一個名字(變量)來指代,而這個名字(變量)對於“外層”包含它的函數而言,是本地變量。一個函數和它的環境變量合在一起,就構成了一個閉包(closure)。在Python中,所謂的閉包是一個包含有環境變量取值的函數對象。環境變量取值被保存在函數對象的closure屬性中。


匿名函數

關鍵字lambda表示匿名函數,冒號前面的x表示函數參數。匿名函數有個限制,就是只能有一個表達式,不用寫return,返回值就是該表達式的結果,如:匿名函數lambda x: x * x。用匿名函數有個好處,因爲函數沒有名字,不必擔心函數名衝突。此外,匿名函數也是一個函數對象,也可以把匿名函數賦值給一個變量,再利用變量來調用該函數。同樣,也可以把匿名函數作爲返回值返回。所謂匿名,意即不再使用def語句這樣標準的形式定義一個函數。這種語句的目的是由於性能的原因,在調用時繞過函數的棧分配。其語法是:
lambda [arg1[, arg2, … argN]]: expression
其中,參數是可選的,如果使用參數的話,參數通常也會在表達式之中出現。


裝飾器與偏函數

  • 裝飾器:Python的decorator可以用函數實現,也可以用類實現。decorator可以增強函數的功能,定義起來雖然有點複雜,但使用起來非常靈活和方便。不希望修改函數或者類的定義,這種在代碼運行期間動態增加功能的方式,稱之爲“裝飾器”(Decorator)。我們要藉助Python的@語法,把decorator置於函數或者類的定義處。
  • 偏函數:簡單總結functools.partial的作用就是,把一個函數的某些參數給固定住(也就是設置默認值),返回一個新的函數,調用這個新函數會更簡單,而這個函數就是一個偏函數。創建偏函數時,實際上可以接收函數對象、*args和**kw這3個參數。
發佈了53 篇原創文章 · 獲贊 12 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章