【script】python中的函數式編程

函數式編程就是一種抽象程度很高的編程範式,純粹的函數式編程語言編寫的函數沒有變量,因此,任意一個函數,只要輸入是確定的,輸出就是確定的,這種純函數我們稱之爲沒有副作用。而允許使用變量的程序設計語言,由於函數內部的變量狀態不確定,同樣的輸入,可能得到不同的輸出,因此,這種函數是有副作用的。

函數式編程的一個特點就是,允許把函數本身作爲參數傳入另一個函數,還允許返回一個函數!

下面介紹一下函數式編程中常見的高階函數:

map():

作用:

map()函數接收兩個參數,一個是函數,一個是Iterable(可迭代對象)map將傳入的函數依次作用到序列的每個元素,並把結果作爲新的Iterator返回。其效果如下:

map(f, [x1, x2, x3, x4]) = [f(x1), f(x2), f(x3), f(x4)]

舉例:

利用map()函數,把用戶輸入的不規範的英文名字,變爲首字母大寫,其他小寫的規範名字。輸入:['adam', 'LISA', 'barT'],輸出:['Adam', 'Lisa', 'Bart']:

def name(l_name):   # 首字母大寫,其它小寫
    l_name = l_name[0].upper() + l_name[1:].lower()
    return l_name
l_name_1 = ['adam', 'LISA', 'barT']
l_name_2 = list(map(name, l_name_1))    # map讓name函數對l_name_1進行遞歸處理
print(l_name_2) # ['Adam', 'Lisa', 'Bart']

相當於:

l_name_1 = ['adam', 'LISA', 'barT']
l_name_2 = []
for name in l_name_1:
    name = name[0].upper() + name[1:].lower()
    l_name_2.append(name)
print(l_name_2)

所以map()可以代替for循環。別看在這裏for循環好像比map()用起來簡單,當代碼中有多個for循環嵌套時,map()在閱讀速度上以及可維護性上都要比for循環好上許多

高階函數多線程用法:

from multiprocessing.dummy import Pool  # 進程池
def name(l_name):
    l_name = l_name[0].upper() + l_name[1:].lower()
    return l_name
pool = Pool(10) # 定義線程數
l_name_1 = ['adam', 'LISA', 'barT']
l_name_2 = pool.map(name, l_name_1)
print(l_name_2)

reduce():

作用:

reduce把一個函數作用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算。其效果如下:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

舉例:

編寫一個prod()函數,可以接受一個list並利用reduce()求積。輸入:[3, 5, 7, 9],輸出:945:

from functools import reduce # reduce在python2中是內置的,在python3中已移除,需要import
def prod(l):
    return reduce(lambda x, y: x*y,l)   # reduce讓lambda創建的匿名函數對l進行兩兩遞歸處理
print('3 * 5 * 7 * 9 =', prod([3, 5, 7, 9]))
if prod([3, 5, 7, 9]) == 945:
    print('測試成功!')
else:
    print('測試失敗!')
# 輸出:3 * 5 * 7 * 9 = 945 \n 測試成功!

filter():

作用:

map()類似,filter()也接收一個函數和一個序列。不同的是,filter()把傳入的函數依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素。其效果如下:

filter(f, [x1, x2, x3, x4]) = [x1, x3, x4]  # f(x1) = True, f(x2) = False, f(x3) = True, f(x4) = True

舉例:

利用filter()函數把一個序列中的空字符串刪掉:

def not_empty(s):
    return s and s.strip()
print(list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))) # filter讓not_empty函數對列表進行遞歸處理,並返回['A', 'B', 'C']

相當於:

s1 = ['A', '', 'B', None, 'C', '  ']
s2 = []
for e in s1:
    if e != None:
        if e.strip() != '':
            s2.append(e)
        else:  pass
    else: pass
print(s2)

map()可以代替for,同樣的filter()也可以代替if-else,理由同上

sorted():

作用:

排序也是在程序中經常用到的算法。無論使用冒泡排序還是快速排序,排序的核心是比較兩個元素的大小。如果是數字,我們可以直接比較,但如果是字符串或者兩個dict呢?直接比較數學上的大小是沒有意義的,因此,比較的過程必須通過函數抽象出來。其效果如下:

sorted(f, [x1, x2, x3, x4]) = [x4, x2, x3, x1]  # f(x4) > f(x2) > f(x3) > f(x1)

舉例:

用sorted()對列表中元組分別按名字進行排序:

l = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t): # 函數作用,取出元組中的第一個元素
    return t[0]
L2 = sorted(l, key=by_name) # sorted讓key指定的by_name函數對l進行遞歸處理,返回['Bob', 'Adam', 'Bart', 'Lisa'],之後再做排序
print(L2)   # [('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]

 

參考鏈接:

https://www.liaoxuefeng.com/wiki/1016959663602400/1017434209254976

發佈了38 篇原創文章 · 獲贊 3 · 訪問量 3772
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章