13-01高階函數

明確目的(本章知識點)

  1. 什麼是高階函數
  2. 實例-方便理解函數是如何作爲參數或者返回值的
  3. 函數作爲參數的場景
  4. 函數作爲返回值的場景
  5. 函數即作爲參數又作爲返回值的場景
  6. python內置3個高階函數-map、filter、reduce

模擬教學(嘗試講清楚)

1、什麼是高階函數

  1. 有一個函數,它的參數是函數
  2. 有一個函數,它的返回值是函數
  3. 有一個函數,它的參數和返回值都是函數
  4. 如上三個函數,都是高階函數。一句話總結就是:(參數是函數)或者(返回值是函數)的函數,就是高階函數。

2、實例-方便理解函數是如何作爲參數或者返回值的

廖雪峯大神寫得非常好,我就直接複製整理過來了。

以Python內置的求絕對值的函數abs()爲例,調用該函數用以下代碼:

>>> abs(-10)
10

但是,如果只寫abs呢?

>>> abs
<built-in function abs>

可見,abs(-10)是函數調用,而abs是函數本身。

要獲得函數調用結果,我們可以把結果賦值給變量:

>>> x = abs(-10)
>>> x
10

但是,如果把函數本身賦值給變量呢?

>>> f = abs
>>> f
<built-in function abs>

結論:函數本身也可以賦值給變量,即:變量可以指向函數。

如果一個變量指向了一個函數,那麼,可否通過該變量來調用這個函數?用代碼驗證一下:

>>> f = abs
>>> f(-10)
10

成功!說明變量f現在已經指向了abs函數本身。直接調用abs()函數和調用變量f()完全相同。

3、函數作爲參數的場景

  1. 先來個簡單的例子理解理解

如下add函數就是高階函數,f就是一個函數

In [156]: def add(x, y, f):
...: return f(x) + f(y)
...:
In [157]: add(-5, 6, abs) 
Out[157]: 11
  1. 實際應用中的場景,比如排序算法
    需求:寫一個函數,傳入一個列表。並對列表的值進行排序
例1:實現版本1,先實現最基本的功能,默認是逆序
In [178]: def sort(it): 
     ...:     ret = [] 
     ...:     for x in it: 
     ...:         for i, e in enumerate(ret): 
     ...:             if x > e: 
     ...:                 ret.insert(i, x) 
     ...:                 break 
     ...:         else: 
     ...:             ret.append(x) 
     ...:     return ret 

In [179]: sort([1, 2, 34, 6, 8, 5])
Out[179]: [34, 8, 6, 5, 2, 1]

例2:例1中只支持順序排序,如果我要順序排序呢,是否又要重寫一個呢,來個版本2的,當r爲True時就是順序了
In [180]: def sort(it, r=False): 
     ...:     ret = [] 
     ...:     for x in it: 
     ...:         for i, e in enumerate(ret): 
     ...:             if r: 
     ...:                 if x < e: 
     ...:                     ret.insert(i, x) 
     ...:                     break 
     ...:             else: 
     ...:                 if x > e: 
     ...:                     ret.insert(i, x) 
     ...:                     break 
     ...:         else: 
     ...:             ret.append(x) 
     ...:     return ret 

In [25]: sort([38, 99, 24, 44, 18])
Out[25]: [99, 44, 38, 24, 18]

In [26]: sort([38, 99, 24, 44, 18], r=True)
Out[26]: [18, 24, 38, 44, 99]

例3:功能上要少寫重複代碼,不然一旦修改則要修改2處,改進版3
In [181]: def sort(it, r=False): 
     ...:     ret = [] 
     ...:     def cmp(a, b): 
     ...:         if r: 
     ...:             return x < e 
     ...:         else: 
     ...:             return x > e 
     ...:
     ...:     for x in it: 
     ...:         for i, e in enumerate(ret): 
     ...:             if cmp(x, e): 
     ...:                 ret.insert(i, x)     # 對比例2,當要修改,本實例只需要修改一次
     ...:                 break 
     ...:         else: 
     ...:             ret.append(x) 
     ...:     return ret 

例4:使用高階函數來寫該函數,lambda是匿名函數(單行函數)
In [38]: def sort(it, cmp=lambda a, b: a < b):
    ...:     ret = []
    ...:     for x in it:
    ...:         for i, e in enumerate(ret):
    ...:             if cmp(x, e):
    ...:                 ret.insert(i, x)
    ...:                 break
    ...:         else:
    ...:             ret.append(x)
    ...:     return ret
    ...:

In [39]: sort([1, 2, 34, 6, 8, 5])
Out[39]: [1, 2, 5, 6, 8, 34]

In [40]: sort([1, 2, 34, 6, 8, 5], lambda a, b: a > b)
Out[40]: [34, 8, 6, 5, 2, 1]
  1. 部分總結
    1. 使用高階函數的方式可以少寫很多代碼。也就是說寫代碼可以不用高階函數(會造成代碼量多邏輯複雜)
    2. 函數作爲參數:通常用於大多數邏輯固定,少部分邏輯不固定的場景。
    3. python內置了一個排序函數sorted(),就是典型的函數作爲參數的函數

4、函數作爲返回值的場景

  1. 先來個簡單的例子理解理解
In [12]: def build(x, y):
    ...:     def tmp_der():         # 定義一個函數
    ...:         return x * y
    ...:     return tmp_der         # return把這個函數作爲結果返回
    ...:

In [13]: f = build(3, 5)        # 把return賦值給了f,return的是一個函數, f的值也是一個函數

In [14]: f         # f的值,python一切皆對象,函數也是一個對象
Out[14]: <function __main__.build.<locals>.tmp_der()>

In [15]: f()      # 既然是函數那麼就可以調用,f()調用一下就有結果了
Out[15]: 15
  1. 實際應用中的場景,比如
    經驗不夠,編不出來

  2. 部分總結
    函數作爲返回值:通常是用於閉包的場景,需要封裝一些變量

5. 函數即作爲參數又作爲返回值的場景

裝飾器:它的參數是一個函數,返回值也是一個函數。
那麼可以說,所有的裝飾器都是高階函數的一種,理解了裝飾器就理解了此知識點

詳見裝飾器篇

6. python內置3個高階函數-map、filter、reduce

經驗不夠,編不出來

重複回顧(老佔位行)

  1. 用紙寫出本章知識點
  2. 問問自己該知識點有哪些沒理解透徹
  3. 如果理解透徹就將概念簡化
  4. 如果不可以,重新模擬教學

概念簡化(把知識點簡化成一兩句話)

  1. 什麼是高階函數,爲什麼要用高階函數

    (參數是函數)或者(返回值是函數)的函數,就是高階函數。
    使用高階函數少些很多代碼,優化業務代碼邏輯。

  2. 理解函數是如何作爲參數或者返回值

    函數fn, 不調用時是一個python函數對象, fn()調用時就是一個函數

  3. 函數作爲參數的場景

    通常用於大多數邏輯固定,少部分邏輯不固定的場景。經驗不夠,編不出來

  4. 函數作爲返回值的場景

    通常是用於閉包的場景,需要封裝一些變量。經驗不夠,編不出來閉包是什麼暫時不知道

  5. 函數即作爲參數又作爲返回值的場景

    裝飾器的時候再深入理解

  6. python內置3個高階函數-map、filter、reduce

    三個函數分別用來做什麼。經驗不夠,編不出來

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章