標籤:結合 描述 概念 函數的參數 對象 object 特性 traceback markdown
基本概念
函數式編程,是一種抽象程度很高的編程範式,純粹的函數式程式設計語言編寫的函數沒有變數。因此,任意一個函數,只要輸入確定,輸出就確定的這種函數我們稱之為純函數,我們稱這種函數沒有副作用。而允許使用白變數的程式設計語言,由於函數內部的變數狀態是不確定的,同樣的輸入可能有不同的輸出,我們稱這種函數為有副作用的。
函數式編程的一個特點就是,允許把函數本身作為參數傳遞給另一個函數,還允許返回一個函數!
Python對函數式編程提供部分支援。由於Python允許使用變數,因此,Python不是純函數式程式設計語言。
(這部分內容摘抄與廖雪峰老師的部落格文章,自己也進行了學習)
高階函數
變數可以指向函數
#變數可以指向函數f = abs;print(abs(-10));#10print(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的特性。就是說一個函數可可以作為另一個函數的參數。上面的學習例子都是很簡單的,需要自己不斷的練習。
python函數式編程之高階函數學習