5 Python 基礎: 高階函數學習實踐
- 2019 年 10 月 4 日
- 筆記
目錄
5 Python 基礎: 高階函數學習實踐,共有 1 部分:
- 高階函數
高階函數
編寫高階函數,就是讓函數的參數能夠接收別的函數。
變數可以指向函數
以Python內置的求絕對值的函數abs()為例,調用該函數用以下程式碼:abs(-10)
什麼是函數
函數本身也可以賦值給變數,即:變數可以指向函數,函數名其實就是指向函數的變數
print(abs(-1)) print(abs) x = abs(-1) print x f = abs print(f) print(f(-1)) # 結果: 1 <built-in function abs> 1 <built-in function abs> 1
print(abs(-1)) abs = 2 print(abs(-1)) # 結果: 1 TypeError: 'int' object is not callable
什麼是高階函數
變數可以指向函數,函數的參數能接收變數,那麼一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。
def fun(x, y, f): print(f(x), f(y)) fun(1, -2, abs) # 結果: 1 2
內置高階函數
map函數
map( ) 函數接收兩個參數,一個是函數,一個是序列, map 將傳入的函數依次作用到序列的每個元素,並把結果作為新的 list 返回。
def fun(x): return x * x print(map(fun, range(5))) # 結果: [0, 1, 4, 9, 16] ------------------------------------- print(map(str, [1, 2, 3])) # 結果: ['1', '2', '3']
reduce函數
reduce把一個函數作用在一個序列x1, x2, x3…上,這個函數必須接收兩個參數,reduce 把結果繼續和序列的下一個元素做累積計算。
def add(x, y): return x + y print(reduce(add, range(5))) # 結果: 10
其實其運行過程為:add(add(add(add(0+1)+2)+3)+4)=10
綜合編程:寫出把 str 轉換為 int 的函數(eg:』12345』–12345)
def fun(N): return {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9}[N] def fun1(x, y): return x * 10 + y print(reduce(fun1,map(fun,"12345"))) # 結果: 12345
filter函數
filter( ) 也接收一個函數和一個序列。和 map( ) 不同的時,filter( ) 把傳入的函數依次作用於每個元素,然後根據返回值是 True還是 False 決定保留還是丟棄該元素
在一個 list 中,刪掉偶數,只保留奇數:
def fun(n): return n % 2 == 1 print(filter(fun,range(5))) # 結果: [1, 3]
sorted函數
排序也是在程式中經常用到的演算法。無論使用冒泡排序還是快速排序,排序的核心是比較兩個元素的大小。通常規定如下:
x < y, return -1 x == y, return 0 x > y, return 1 ---------------------------- print(sorted([3, 1, 2])) print(sorted([3, 1, 2], reverse=True)) # 結果: [1, 2, 3] [3, 2, 1]
排序數字字元
li = ['2', '1', '4', '3'] print(sorted(li, key=int)) # 結果: ['1', '2', '3', '4']
匿名函數
• 當我們在傳入函數時,有些時候,不需要顯式地定義函數,直接傳入匿名函數更方便。
• 關鍵字 lambda 表示匿名函數,冒號前面的 x 表示函數參數。
print(map(lambda x: x * x, [1, 2, 3, 4])) def fun(x): return x * x print(map(fun, [1, 2, 3, 4])) # 結果: [1, 4, 9, 16] [1, 4, 9, 16]
• 匿名函數有隻能有一個表達式,不用寫 return ,返回值就是該表達式的結果。
• 因為匿名函數沒有名字,不必擔心函數名衝突。此外,匿名函數也是一個函數對象,也可以把匿名函數賦值給一個變數,再利用變數來調用該函數;
f = lambda x: x * x print(f) print(f(3)) # 結果: <function <lambda> at 0x7fde80eb7938> 9
• 把匿名函數作為返回值返回。
def fun(x, y): return lambda: x * x + y * y print(fun(1, 2)) f = fun(1, 2) print(f()) # 結果: <function <lambda> at 0x7f5c2942a9b0> 5
傳入多個參數:
f = lambda x,y =1,*args,**kwargs :(x*y,args,kwargs) print(f(2,4,5,a=1,b=5)) # 結果: (8, (5,), {'a': 1, 'b': 5})
練習
1. (華為機試練習)
題目描述:數據表記錄包含表索引和數值,請對錶索引相同的記錄進行合併,即將相索引的數值進行求和運算,輸出按照key值升序進行輸出。
– 輸入描述:先輸入鍵值對的個數,然後輸入成對的index和value值,以空格隔開
– 輸出描述:輸出合併後的鍵值對(多行)
– 示例1:
輸入
4 0 1 0 2 1 2 3 4
輸出
0 3 1 2 3 4
腳本:
d = dict() Num = input("please input Num: ") for i in range(Num): N = raw_input("please input index and value: ") if d.has_key(N.split()[0]): New = str(int(d[N.split()[0]]) + int(N.split()[1])) d.pop(N.split()[0]) d.setdefault(N.split()[0], New) else: d.setdefault(N.split()[0], N.split()[1]) for j, k in sorted(d.items()): print(j, k)
2. 題目描述
現在IPV4下用一個32位無符號整數來表示,一般用點分方式來顯示,點將IP地址分成4部分,每個部分為8位,表示成一個無符號整數(因此不需要用正號出現),10.137.17.1,是我們非常熟悉的IP地址,一個IP地址串中沒有空格出現(因為要表示成一個32數字)。現在需要你用程式來判斷IP是否合法。
輸入描述:輸入一個ip地址
輸出描述:返回判斷的結果YES or NO
示例1:
輸入: 10.138.15.1
輸出: YES
腳本:
IP = raw_input("please input IP: ") for i in IP: if not (i.isdigit() or i =="."): print("NO") exit(1) else: if len(IP.split(".")) == 4: for j in range(4): if int(IP.split(".")[j])>=0 and int(IP.split(".")[j])<=255: print("YES") exit() else: print("NO") exit(1) else: print("NO") exit(1)
3.函數式編程考察
用 filter()進行函數式編程,寫一段程式碼來給出一個年份的列表並返回一個只有閏年的列表列表解析式實現方式呢?
def fun(N): if (N % 400 == 0) or (N % 4 == 0 and N % 100 != 0): return True else: return False Year = raw_input("please input Year: ") li = [] for i in Year: if not (i.isdigit() or i.isspace()): print("input Error!!!") exit(1) for j in Year.split(): li.append(int(j)) li = list(set(li)) print(filter(fun, li))
4.攜程旅行網
給定一個整型數組,將數組中所有的」0」移到末尾,非」0」項保持順序不變在原始數組上進行操作,勿創建新的數組
輸入
第一行是數組長度 後續每一行是數組的第一條記錄
輸出
調整後的數組內容
樣例輸入
4 0 7 0 2
樣例輸出
7 2 0 0
array = [1, 0, 4, 0, 3, 2, 0, 1] print(sorted(array, key=lambda x: 1 if x == 0 else 0)) # 結果: [1, 4, 3, 2, 1, 0, 0, 0]