基本概念
函數式編程,是一種抽象程度很高的編程範式,純粹的函數式編程語言編寫的函數沒有變量。因此,任意一個函數,只要輸入確定,輸出就確定的這種函數我們稱之爲純函數,我們稱這種函數沒有副作用。而允許使用白變量的程序設計語言,由於函數內部的變量狀態是不確定的,同樣的輸入可能有不同的輸出,我們稱這種函數爲有副作用的。
函數式編程的一個特點就是,允許把函數本身作爲參數傳遞給另一個函數,還允許返回一個函數!
Python對函數式編程提供部分支持。由於Python允許使用變量,因此,Python不是純函數式編程語言。
(這部分內容摘抄與廖雪峯老師的博客文章,自己也進行了學習)
高階函數
變量可以指向函數
#變量可以指向函數 f = abs; print(abs(-10));#10 print(f(-10));#10 #在這裏用f和abs調用的結果和效果是一樣的
說明變量f 已經指向了函數 abs本身。
函數名也是變量
函數名就是指向函數的變量。如:abs = 10; print(abs(-10)); # Traceback (most recent call last): # File "test01.py", line 164, in <module> # print(abs(-10)); # TypeError: 'int' object is not callable
abs已經被賦值10,是一個指向10的變量了,就不能通過abs(-10)來調用該函數了,因爲abs這個變量已經不指向求絕對值函數了。
傳入函數
就是一個函數可以作爲另一個函數的參數,這種函數稱爲高階函數。#一個簡單的高階函數 def add(x, y, f): return f(x) + f(y); print(add(5, -6, abs));#11
map/reduce
python內建了map()和reduce()函數。
map()函數
map函數接收兩個參數,一個是函數,一個是iterable(可迭代的對象),map將傳入的函數一次作用到序列的每個元素,並把結果作爲新的iterator返回。#map()函數 def f(x): return x * x; r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]); print(list(r)); # [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce()函數
該函數必須接收兩個參數,reduce把函數結果繼續和序列的下一個元素做累積計算。
如:累加#reduce()函數 from functools import reduce; def add1(x, y): return x + y; print(reduce(add1, [1, 3, 5, 7, 9]));#25
這並不是reduce的用武之地,當我們要把上面的數列變成整數13579時,reduce就排上用場了:
def fn(x, y): return x * 10 + y; print(reduce(fn, [1, 3, 5, 7, 9]));
這個例子也沒什麼意義,但是當我們要把字符串 str 轉換成int的函數時,就用上了reduce(結合map)。
filter()函數
filter
python內置的filter函數用於過濾序列。和map類似也接收一個函數和一個序列,但是不同的是,filter把傳入的函數依次作用於每個元素,然後根據返回值是true還是false決定保留還是丟棄該元素。
在一個list中,刪掉偶數,只保留奇數:#filter函數 #在一個list中刪除偶數,只保留奇數 def is_odd(n): return n % 2 == 1; print(list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))); # 1, 5, 9, 15
用filter求素數
思想:計算素數的一個方法是埃氏篩法,它的算法理解起來非常簡單:首先,列出從2開始的所有自然數,構造一個序列:
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …
取序列的第一個數2,它一定是素數,然後用2把序列的2的倍數篩掉:
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …
取新序列的第一個數3,它一定是素數,然後用3把序列的3的倍數篩掉:
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …
取新序列的第一個數5,然後用5把序列的5的倍數篩掉:
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …
不斷篩下去,就可以得到所有的素數。
註明:該算法描述來源於廖雪峯老師的文章。
sorted()函數
排序算法
#sorted函數排序
print(sorted([36, -2, 5, 7, 1, -10]));
# [-10, -2, 1, 5, 7, 36];
sorted也是一個高階函數,可以接受一個key函數來實現自定義的排序,列如按絕對值大小排序:
#sorted函數排序
print(sorted([36, -2, 5, 7, 1, -10], key=abs));
# [1, -2, 5, 7, -10, 36]
sorted函數可以用來對字符串進行排序。
sorted()也是一個高階函數。用sorted()排序的關鍵在於實現一個映射函數。
總結
對函數式編程的學習這部分比較重要,學習這部分讓我想到了前端框架reactJs,react也是強調函數式編程的,也是react的特性。就是說一個函數可可以作爲另一個函數的參數。上面的學習例子都是很簡單的,需要自己不斷的練習。