1. 程式人生 > >Python高階函式及函式柯里化

Python高階函式及函式柯里化

1 Python高階函式

  接收函式為引數,或者把函式作為結果返回的函式為高階函式。

 1.1 自定義sort函式

  要求:仿照內建函式sorted,自行實現一個sort函式。內建函式sorted函式是返回一個新的列表,可以設定升序或降序,也可以設定一個排序的函式,自定義的sort函式也要實現這個功能。

  sort函式實現思路:新建一個列表,遍歷原列表,和新列表的值一次比較決定如何插入到新列表中。

  sort函式版本一的實現,程式碼如下:

 1 def sort(iterable):
 2     ret = []
 3     for x in iterable:
 4         for i, y in enumerate(ret):
 5             if x > y:  # 找到比ret中大的位置上的數插入相應位置,降序排序
 6                 ret.insert(i, x)
 7                 break
 8         else:  # 不大於,說明x在ret中是最小的,直接將其追加至ret後
 9             ret.append(x)
10     return ret
11 
12 if __name__ == '__main__':
13     lst = [1,2,3,4,5,6,7,8]
14     print(sort(lst))
View Code

  上述程式碼只能實現的,升序的排列方式,那麼現在想通過一個引數來控制排列的方式,該如何實現呢?看如下程式碼:

 1 def sort(iterable, reverse=False):
 2     ret = []
 3     for x in iterable:
 4         for i, y in enumerate(ret):
 5             flag = x > y if reverse else x < y  # 預設排序方式為升序
 6             if flag:  # 找到比ret中大的位置上的數插入相應位置,降序排序
 7                 ret.insert(i, x)
 8                 break
 9         else:  # 不大於,說明x在ret中是最小的,直接將其追加至ret後
10             ret.append(x)
11     return ret
View Code

  通過對reverse引數的boole值進行判斷,看使用降序還是升序,那麼能不能將對x,y大小的判斷的功能抽象出來,作為一個排序的函式傳給sort函式?看如下程式碼:

 1 def comparator(x, y):
 2     if x > y:
 3         return False
 4     else:
 5         return True
 6 
 7 def sort(iterable, reverse=False, key=None):
 8     ret = []
 9     for x in iterable:
10         for i, y in enumerate(ret):
11             flag = key(x, y) if reverse else not key(x, y)
12             if flag:  # 找到比ret中大的位置上的數插入相應位置,預設降序排序
13                 ret.insert(i, x)
14                 break
15         else:  # 不大於,說明x在ret中是最小的,直接將其追加至ret後
16             ret.append(x)
17     return ret
View Code

  該程式碼中在呼叫sort函式,每次都得傳入一個函式才能實現排序,那麼能不能用一個函式的表示式作為一個預設值引數進行傳入呢?這就要用到匿名函式,程式碼如下:

 1 def sort(iterable, reverse=False, key=lambda a,b:a>b):
 2     ret = []
 3     for x in iterable:
 4         for i, y in enumerate(ret):
 5             flag = key(x, y) if not reverse else not key(x, y)
 6             if flag:  # 找到比ret中大的位置上的數插入相應位置,預設降序排序
 7                 ret.insert(i, x)
 8                 break
 9         else:  # 不大於,說明x在ret中是最小的,直接將其追加至ret後
10             ret.append(x)
11     return ret
View Code

  一步一步的將程式碼實現到這,已經將sort函式從最初實現的簡單排序,改成最終的可以設定升序和排序,以及設定排序的規則的函式。這樣就將sort函式改成了一個高階函式。

1.2 內建函式-高階函式

1.2.1 sorted函式

  sorted(iterable[, key][, reverse]),內建函式sorted函式中可選的key引數用於提供一個函式,它會應用到各個元素上進行排序。例如,如果想根據單詞的長度進行排序,只需將len函式傳給key引數,如下示例:

   任何單引數函式都能作為key引數的值,再比如實現:將每個單詞的字母反轉後,在對其進行排序。實現如下:

    在函數語言程式設計中,Python 3中常用的高階函式還有,map、filter。

1.2.2 filter函式

  filter(function, iterable),過濾可迭代物件的元素,返回一個迭代器。function是一個具有單引數的函式,返回bool值。

1 list(filter(lambda x: x%3==0, [1,9,55,150,-3,78,28,123]))  # 過濾出數列中能被3整除的數字

1.2.3 map函式

  map(function, *iterables),對多個可迭代物件的元素按照指定的函式進行對映,返回一個迭代器。

list(map(lambda x:2*x+1, range(5)))
dict(map(lambda x: (x%5,x) , range(500)))

  在Python 3中,map和filter返回生成器(一種迭代器),因此現在它們的直接替代品是列表推導式和生成器表示式。

2 柯里化Currying

  柯里化指的是將原來接收兩個引數的函式變成新的接收一個引數的函式的過程。新的函式返回一個以原有第二個引數為引數的函式。其形式相當於將z = f(x, y)轉換成z = f(x)(y)的形式。舉例:

 1 # 將加法函式柯里化
 2 def add(x, y):
 3     return x + y
 4 
 5 # 柯里化
 6 def add(x):
 7     def inc(y):
 8         return x + y
 9     return inc
10 
11 foo = add(2)
12 print(foo(3))
13 # 相當於
14 print(add(2)(3))
View Code

  通過柯里化的過程可知,在柯里化時使用巢狀函式就可以將函式轉換成柯里化函式。

  從前面的閉包,以及現在的高階函式以及函式的柯里化,這些都是Python裝飾器的基礎,有了這些基礎,就可以學習Python中的裝飾