白话 Python 的函数式编程
今天和大家聊聊 Python 的函數式編程特性。所謂函數式編程,就是指代碼中每一塊都是不可變的(immutable),都是由 pure function 的形式組成。這里的 pure function 是指函數本身相互獨立,互不影響,對于相同的輸入,總會有相同的輸出。也就是我們常說的沒有副作用。舉個很簡單的例子,比如,對于一個列表,我想讓列表中的元素值都變為原來的兩倍,我們可以寫成下面的形式:
def multiply_2(l):for index in range(0, len(l)):l[index] *= 2return l這就不是一個 pure function,因為列表中元素的值被改變了,如果我調用 multiply_2() 這個函數多次,那么每次得到的結果都不一樣。要想讓其成為一個pure function,就得寫成下面的形式,重新創建一個新的列表并返回。
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' def multiply_2_pure(l):new_list = []for item in l:new_list.append(item * 2)return new_list函數式編程的優點主要在于其 pure function 和不可變的特性使得程序更加健壯,易于 debug 和測試,缺點主要在于限制多,難寫。當然 Python 不同于其他一些語言,比如 Scala,他并不是一門純粹的函數式編程語言,但是 Python 也提供了一些函數式編程的特性,值得我們了解和學習。
Python 主要提供了這么幾個函數 Map, Filter 和 Reduce,通常結合匿名函數 lambda 一起使用,我逐一介紹一下:
對于 Map(function, iterable) 函數,前面的例子提過,他表示對 iterable 中的每個元素運用 function 這個函數,最后返回一個新的可遍歷的集合,比如上面對列表中每個元素乘2用map可以表示為
l = [1, 2, 3, 4, 5] new_list = map(lambda x: x * 2, l) # [2, 4, 6, 8, 10]我們再來看一下 Python 提供的函數式編程的接口的性能,就以 Map 為例,上述的例子還可以用 for 循環和 list comprehension 實現,我們來比較一下他們的速度:
python3 -mtimeit -s’xs=range(1000000)' 'map(lambda x: x*2, xs)'輸出結果:2000000 loops, best of 5: 171 nsec per looppython3 -mtimeit -s’xs=range(1000000)' '[x * 2 for x in xs]'輸出結果:5 loops, best of 5: 62.9 msec per looppython3 -mtimeit -s’xs=range(1000000)’ 'l = []' 'for i in xs: l.append(i * 2)'輸出結果:5 loops, best of 5: 92.7 msec per loop可以看到 map 是最快的,因為 map 函數是直接由 C 語言寫的,運行時不需要通過 Python 解釋器間接調用,因此運行速度最快。
對于 Filter(function, iterable) 函數,和 map 函數類似,function 同樣表示一個函數對象,表示對 iterable 中的每個元素使用 function 判斷,返回 True 或者 False,最后將返回 True 的元素組成一個新的可遍歷的集合,比如我要返回一個列表中的所有偶數,可以寫成
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' l = [1, 2, 3, 4, 5] new_list = filter(lambda x: x % 2 == 0, l) # [2, 4]對于 Reduce(function, iterable) 函數,通常用于對一個集合做一些累積操作。function 同樣是一個函數對象,規定他有兩個參數,表示對 iterable 中的每個元素以及上一次調用后的結果運用 function 進行計算,因此最后返回的是一個單獨的數值,比如,我想要計算列表元素的乘積,可以表示為:
l = [1, 2, 3, 4, 5] product = reduce(lambda x, y: x * y, l) # 1*2*3*4*5 = 120類似的,Filter,Reduce 的功能也可以用 for 循環或者 list comprehension 來實現,但是速度都不如 Filter 或者 Reduce。
通常來說,如果你想對一個集合中的元素進行一些操作,如果是一些非常簡單的操作,比如相加,累積,那么我們優先考慮 Map、Filter、Reduce 或者 list comprehension 的形式。
在這兩者之中,如果數據量非常大,比如機器學習的應用,那我們一般更傾向于函數式編程的表示,因為效率更高,如果數據量不多,并且你想要自己的程序更加 Pythonic(Python 化),那么運用 list comprehension 的情況也是很常見的。如果你要對集合中的元素做一些比較復雜的操作,考慮到代碼的可讀性,這時我們通常會使用 for 循環,因為更加清晰明了。
總結
以上是生活随笔為你收集整理的白话 Python 的函数式编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 干货丨你知道Python中a += b和
- 下一篇: Mozilla的Python3使用情况