天天看點

Python 進階_函數式程式設計目錄函數式程式設計Python 函數式程式設計的特點高階函數匿名函數 lambda函數式程式設計相關的内置函數最後

<a href="#%E7%9B%AE%E5%BD%95">目錄</a>

<a href="#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B">函數式程式設計</a>

<a href="#python-%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B%E7%9A%84%E7%89%B9%E7%82%B9">Python 函數式程式設計的特點</a>

<a href="#%E9%AB%98%E9%98%B6%E5%87%BD%E6%95%B0">高階函數</a>

<a href="#%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0-lambda">匿名函數 lambda</a>

<a href="#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B%E7%9B%B8%E5%85%B3%E7%9A%84%E5%86%85%E7%BD%AE%E5%87%BD%E6%95%B0">函數式程式設計相關的内置函數</a>

<a href="#filter-%E5%BA%8F%E5%88%97%E5%AF%B9%E8%B1%A1%E8%BF%87%E6%BB%A4%E5%99%A8">filter 序列對象過濾器</a>

<a href="#map">map</a>

<a href="#reduce-%E6%8A%98%E5%8F%A0">reduce 折疊</a>

<a href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E6%8E%92%E5%BA%8F%E5%87%BD%E6%95%B0">自定義的排序函數</a>

<a href="#%E6%9C%80%E5%90%8E">最後</a>

首先要确定一點就是:函數 != 函數式,函數式程式設計是一種程式設計的範式。

特點:

把計算視為函數而非指令

純函數式程式設計,不需要變量,沒有副作用,測試簡單

支援高階函數,代碼簡潔

需要注意的是,Python 不是也不可能會成為一種純函數是程式設計語言,但 Python 仍支援許多有價值的函數式程式設計語言的建構方法。

Python 不是純函數是程式設計,因為 Python 支援變量

Python 支援高階函數,而且函數也可以作為變量傳入

Python 支援閉包,可以傳回一個函數

首先要明确一點,函數是由變量來引用的,這也是一個 Python 的特性:将對象引用和對象分離。

EG:

高階函數: 能夠接收函數作為一個參數的函數,就是高階函數。

下面定義一個高階函數:

函數 add 接收内建函數 abs 作為一個參數,是以 add 是一個高階函數。

格式:

匿名函數,顧名思義就是沒有名字的函數,可以忽略函數定義的函數。是以匿名函數的好處之一就是建立簡易、友善,不需要以标準的定義方式(def)來建立。而且匿名函數可以如一般函數那樣傳回一個 callable 的函數對象,是以匿名函數一般會指派給一個變量,或者直接作為一個函數實參來使用。從匿名函數的文法格式來看,其缺點也很明顯,就是其函數體隻能是一條 expression 而不能是一條關鍵字語句,如:<code>print</code>

NOTE: 因為匿名函數可以快速的傳回一個函數對象,并且可以直接作為一個函數的實參使用,是以匿名函數經常被用于建構函數式的程式設計中。

EXAMPLE:

上面兩種方式的結果是一緻的。

注意: 如果 lambda 傳回的對象沒有指派給一個變量,那麼這個函數對象的引用 == 0,會被垃圾回收掉。

Python 提供了幾個與函數式程式設計相關的内置函數,之是以說與函數式程式設計相關是因為這幾個内置函數都需要接收一個函數對象作為參數,而這個函數對象通常由 lambda 來提供。

讓序列對象中的每一個元素都通過一個指定的過濾器,最終符合過濾條件(Return True)的元素會被傳回為一個新的序列。

要自己實作一個 filter 函數,并不難。EG.

EXAMPLE 1:求偶數

EXAMPLE 2:删除 None 或者空字元串

注意: 傳入 filter 的函數最終的傳回值一定是 True or False

map 和 filter 很類似,但 map 函數通過把函數參數依次作用在 seq 的每個元素上,得到一個新的 seq 并傳回。而且 map 的函數參數不要求一定要傳回 True or False 。除此之外, map 還能處理多個序列參數。

EXAMPLE 1:處理單個序列對象

EXAMPLE 2:處理多個序列對象

注意:如果傳遞多個序列對象給 map 時,其處理的算法如下

1. 并行的将多個序列中 index 相同的元素擷取,并捆綁到同一個元組中

2. 将這一個元組傳遞給函數參數中進行處理。

是以需要注意的是,兩個序列的元素個數是否一緻,函數參數是否能正确的處理這個元組對象

從這個例子可以看出 map 可以完成一個簡單的 zip 功能,這是由其内部的實作算法決定的。

reduce 需要傳入一個 二進制函數(具有兩個形參的函數) 、一個序列對象和一個可選的 初始化器。

其最常用的例子就是 累加:

等效于:<code>reduce(func, [1, 2, 3]) ⇒ func(func(1, 2), 3)</code>

Python 内置了一個排序函數 sorted

時 sorted 也是一個高階函數,它可以接收一個比較函數來實作自定義排序。。

比較函數的定義是:傳入兩個待比較的元素 x, y

1. 如果 x 應該排在 y 的前面,傳回 -1

2. 如果 x 應該排在 y 的後面,傳回 1

3. 如果 x 和 y 相等,傳回 0

是以我們可以自定義一個比較函數,并且傳遞給 sorted 函數:

本篇給出了一些内置高階函數的例子,其實在程式設計中使用得更多的是自定義的高價函數,其中 閉包 就是一種非常常用的函數式程式設計。