python 高階函數
1、一等公民
函數在 Python 是一等公民(First-Class Object)
函數也是對象,是可調用對象
函數可以作為普通變數,也可以作為函數的參數、返回值
2、高階函數(High-order Function)
數學概念 y=f(g(x))
在數學和電腦科學中,高階函數應當是至少滿足下面一個條件的函數:
接受一個或多個函數作為參數
輸出一個函數
# 高階函數,例1: def counter(base): def inc(step=1): # 局部變數 nonlocal base base += step return base return inc # 局部變數 inc,每次賦值即重新定義 c1 = counter(5) c2 = counter(5) print(c1(), c2()) # 6 6 print(c1() == c2()) # True,函數對象的返回值相等 print(counter(5) == counter(5)) # False,函數每次調用都不一樣
# 高階函數,例2:
def inc(step=1): return step def counter(): return inc # 返回全局變數 inc c1 = counter() c2 = counter() print(c1 == c2) # True,因為全局變數 inc 不消亡
3、自定義 sort 函數
仿照內建函數 sorted,請自行實現一個 sort 函數(不用使用內建函數),能夠為列表元素排序。
思考:通過練習,思考 sorted 函數的實現原理,map、filter 函數的實現原理。
思路:
內建函數 sorted 函數,它返回一個新的列表,可以設置升序或降序,可以設置一個用於比較的函數(自定義函數也要實現這些功能)
新建一個列表,遍歷原列表,和新列表中的當前值依次比較,決定帶插入數插入到新列表的什麼位置。
實現1:實現升序和倒序
def sort(iterable): # 例:[4, 3, 6] target = [] for x in iterable: for i, y in enumerate(target): # [4] if x < y: # 被插入值小於當前索引值,insert 插入(升序),即當 x > y 時倒序 target.insert(i, x) break # 找到插入位置,結束當前循環 else: target.append(x) return target print(sort([4, 3, 6]))
實現2:實現 reverse
def sort(iterable, *, reverse=False): # 設定 reverse 預設值為 False,不反轉 target = [] for x in iterable: for i, y in enumerate(target): order = x > y if reverse else x < y # 通過 reverse 關鍵字傳參,實現 升序、逆序 if order: target.insert(i, x) break else: target.append(x) return target print(sort([4, 3, 6], reverse=True)) # [6, 4, 3]
實現3:實現 key
def sort(iterable, *, key, reverse=False): target = [] for x in iterable: for i, y in enumerate(target): order = key(x) > key(y) if reverse else key(x) < key(y) # key() if order: target.insert(i, x) break else: target.append(x) return target print(sort([4, 3, '3', 6], reverse=True, key=int)) # [6, 4, 3, '3']
實現4:實現 key 的預設值,key=None
def sort(iterable, *, key=None, reverse=False): target = [] for x in iterable: for i, y in enumerate(target): x = key(x) if key else x y = key(y) if key else y # 不符合(轉換後的結果只是用來比較大小的,不改變最後生成的列表中的元素本身)! # 而且 x 重複計算! order = x > y if reverse else x < y if order: target.insert(i, x) break else: target.append(x) return target print(sort([4, 3, '3', 6], reverse=True, key=str)) # ['6', 4, '3', '3']
# 再改進! def sort(iterable, *, key=None, reverse=False): target = [] for x in iterable: cx = key(x) if key else x # 轉換後的結果只是用來比較大小的,不改變最後生成的列表中的元素本身 for i, y in enumerate(target): cy = key(y) if key else y order = cx > cy if reverse else cx < cy if order: target.insert(i, x) break else: target.append(x) return target print(sort([4, 3, '3', 6], reverse=True, key=str)) # [6, 4, 3, '3']
4、內建高階函數
排序 sorted
定義:sorted(iterable, *, key=None, reverse=False) => list
''' sorted() # 返回新列表 list.sort() # 就地修改 ''' lst = [1, 4, 2, 6, 3] print(sorted(lst, key=lambda x : 7-x)) # 升序,key=lambda x : 7-x,影響排序結果 lst.sort(reverse=True, key=lambda x : 7-x) # 降序,key=lambda x : 7-x,影響排序結果 print(lst) # 執行結果: [6, 4, 3, 2, 1] [1, 2, 3, 4, 6]
映射 map
g = list(map(lambda x : x+1, range(1, 6))) print(g) # [2, 3, 4, 5, 6] g1 = { i:(i, i+1) for i in map(lambda x : x+1, range(1, 6))} print(g1) # {2: (2, 3), 3: (3, 4), 4: (4, 5), 5: (5, 6), 6: (6, 7)} g2 = dict(map(lambda x : (x+1, (x+1, x+2)), range(1, 6))) # 二元組 print(g2) # {2: (2, 3), 3: (3, 4), 4: (4, 5), 5: (5, 6), 6: (6, 7)} g3 = dict(zip(range(2, 7), map(lambda x : (x, x+1), range(2, 7)))) print(g3) # {2: (2, 3), 3: (3, 4), 4: (4, 5), 5: (5, 6), 6: (6, 7)} g4 = dict(map(lambda x, y : [x, y], 'abcde', range(10))) print(g4) # {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4}
過濾 filter
# if element: yield element # 如果這個元素,則返回這個元素 print(filter(None, range(10))) # 惰性對象 print(list(filter(None, range(10)))) # [1, 2, 3, 4, 5, 6, 7, 8, 9] print(list(filter(None, range(-5, 5)))) # [-5, -4, -3, -2, -1, 1, 2, 3, 4] # if fn(element): yield element print(list(filter(lambda x : True, range(10)))) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(list(filter(lambda x : None, range(10)))) # [] print(list(filter(lambda x : 0, range(10)))) # [] # 如果 x%3==0,則為 True print(list(filter(lambda x : x%3==0, [1, 9, 55, 150, -3, 78, 28, 123]))) # [9, 150, -3, 78, 123]