# 高階函數: 變量能夠指向函數-> 函數名也是變量:把函數做爲參數傳入,這樣的函數稱爲高階函數,函數式編程就是指這種高度抽象的編程範式。
# *args 和 **kw # *args是可變參數,args接收的是一個tuple; # **kw是關鍵字參數,kw接收的是一個dict。 # 以及調用函數時如何傳入可變參數和關鍵字參數的語法: # 可變參數既能夠直接傳入:func(1, 2, 3),又能夠先組裝list或tuple,再經過*args傳入:func(*(1, 2, 3)); # 關鍵字參數既能夠直接傳入:func(a=1, b=2),又能夠先組裝dict,再經過**kw傳入:func(**{'a': 1, 'b': 2})。 # 使用*args和**kw是Python的習慣寫法,固然也能夠用其餘參數名,但最好使用習慣用法。
# 1.map L = [1,2,3,4,5,6,7,8,9] def f1(x): return x ** 2 R = list(map(f1,L)) # 讓map的結果轉換爲list print("map結果:",R) # == > map結果: [1, 4, 9, 16, 25, 36, 49, 64, 81] # 1.2 map把元素爲int的轉化爲字符串 S = list(map(str,L)) print("元素類型爲int的轉爲字符串:",S) # == > 元素類型爲int的轉爲字符串: ['1', '2', '3', '4', '5', '6', '7', '8', '9'] # 2.reduce # 2.1 把序列[1, 3, 5, 7, 9]變換成整數13579 from functools import reduce def fn(x, y): return x * 10 + y a = reduce(fn, [1, 3, 5, 7, 9]) print("reduce結果爲:",a) # == > reduce結果爲: 13579 # 練習 # 1.利用map()函數,把用戶輸入的不規範的英文名字,變爲首字母大寫,其餘小寫的規範名字。輸入:['adam', 'LISA', 'barT'],輸出:['Adam', 'Lisa', 'Bart']: def formating(name): return name.title() L = list(map(formating,['adam', 'LISA', 'barT'])) print("練習1的答案:",L) # == > 練習1的答案: ['Adam', 'Lisa', 'Bart'] # 2.Python提供的sum()函數能夠接受一個list並求和,請編寫一個prod()函數,能夠接受一個list並利用reduce()求積: def prod(L1=[]): def fn(x,y): return x * y return reduce(fn,L1) P = prod([1,2,3,4,5,6,7,8]) print("練習2乘積的答案:",P) # == > 練習2乘積的答案: 40320 # 3.利用map和reduce編寫一個str2float函數,把字符串'123.456'轉換成浮點數123.456 def str2float(s): dot = 0 num = 0 if "." in s: for i,x in enumerate(s): if x == ".": dot = len(s) - i - 1 s = s.replace('.','') break else: s = s print("s=",s) def fn(x,y): return x * 10 + y def char2num(s): return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] return reduce(fn,map(char2num,s)) / (10**dot) A = str2float("123.45") print("練習3的結果:",A) # == > 練習3的結果: 123.45 # 3.filter:用於過濾序列和map()相似,filter()也接收一個函數和一個序列。和map()不一樣的是,filter()把傳入的函數依次做用於每一個元素,而後根據返回值是True仍是False決定保留仍是丟棄該元素。 def is_odd(n): return n % 2 == 1 L1 = list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) print(L1) # ==> [1, 5, 9, 15] # 3.1 把一個序列中的空字符串刪掉,能夠這麼寫: def not_empty(s): return s and s.strip() L2 = list(filter(not_empty, ['A', '', 'B', None, 'C', ' '])) # == > # 結果: ['A', 'B', 'C'] # 練習回數是指從左向右讀和從右向左讀都是同樣的數,例如12321,909。請利用filter()濾掉非回數: def is_palindrome(x): if str(x) == str(x)[::-1]: # 本題只須要正順序和反順序相等就知足回數的條件了 return x output = filter(is_palindrome, [x for x in range(1,100)]) print("---->",list(output)) # == > ----> [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99] # 4.sorted 排序算法 sorter1 = sorted([1,3,6,-20,34]) print("升序排列:",sorter1) # 4.1 sorted()函數也是一個高階函數,它還能夠接收一個key函數來實現自定義的排序 sorter2 = sorted([1,3,6,-20,-70],key=abs) print("自定義排序:",sorter2) sorter2 = sorted([1,3,6,-20,-70],key=abs,reverse=True) print("自定義反向排序:",sorter2) # 4.2 字符串排序依照ASCII sorter3 = sorted(["ABC","abc","D","d"]) print("字符串排序:",sorter3) # 4.3 忽略大小寫排序 sorter4 = sorted(["ABC","abc","D","d"],key=str.lower) print("忽略字符串大小寫排序:",sorter4) # 4.4 要進行反向排序,沒必要改動key函數,能夠傳入第三個參數reverse=True: sorter5 = sorted(["ABC","abc","D","d"],key=str.lower,reverse=True) print("忽略字符串大小寫反向排序:",sorter5) # 練習假設咱們用一組tuple表示學生名字和成績:L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)] 請用sorted()對上述列表分別按名字排序: L = [('Bob', 75),('Adam', 90), ('Adam', 92), ('Bart', 66), ('Lisa', 88),('Bart', 100), ('Bart', 88)] print("名字列表L=",L) def by_name(t): return t[0] L2 = sorted(L, key=by_name) print("按照名字排序(默認升序,名字相同的狀況下誰的名字在前誰排在前方):",L2) # 擴展1:若是名字相同,按照分數排序(默認升序) def by_name_score(t): return (t[0],t[1]) L3 = sorted(L, key=by_name_score) print("名字相同,按照分數升序排序:",L3) # 擴展2:若是名字相同,按照分數升序排列 def by_name_score_asc(t): return (t[0],t[1]) L4 = sorted(L,key=by_name_score_asc) print("名字相同,按照分數升序序排列:",L4) # == > [('Adam', 90), ('Adam', 92), ('Bart', 66), ('Bart', 88), ('Bart', 100), ('Bob', 75), ('Lisa', 88)] from operator import itemgetter, attrgetter # 擴展3:若是名字相同,按照分數降序排列(答案待補充) def by_name_score_desc(t): return (t[0], t[1]) L4 = sorted(L,key=by_name_score_desc) print("名字相同,按照分數降序排列(答案待補充):",L4) # 5.返回函數 # 5.1 不須要馬上求和返回求和的函數: def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sum f = lazy_sum(1, 3, 5, 7, 9) print("返回函數:",f()) # ==> 25 # 6.匿名函數:lambda L6 = list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])) print("匿名函數:",L6) # ==> [1, 4, 9, 16, 25, 36, 49, 64, 81] # 7.裝飾器(Decorator):在函數調用先後自動打印日誌,但又不但願修改now()函數的定義,這種在代碼運行期間動態增長功能的方式 import functools def log(func): @functools.wraps(func) def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper @log def now(): print('2015-3-25') print("now函數:",now()) def log(text): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator @log('execute') def now(): print('2015-3-25') print("傳入參數的裝飾器的now函數:",now.__name__) # 7.偏函數:當函數的參數個數太多,須要簡化時,使用functools.partial能夠建立一個新的函數,這個新函數能夠固定住原函數的部分參數,從而在調用時更簡單 import functools int2 = functools.partial(int, base=2) # 經過偏函數聲明一個函數名爲int2的函數,實現轉換成int類型而且參數要和base保持一致最後的結果是10進制的類型 print("二進制的數:",int2("1000")) # ==> 8