函數式編程:允許把函數本身作為參數傳入另一個函數,還允許返回一個函數!
1.高階函數
一個函數可以接收另一個函數作為參數,這種函數稱之為高階函數
abs(-10) 是函數調用 abs是函數本身 abs函數名其實是一個變量名
變量可以指向函數,函數名也是變量名
map()
map(func,seq)
函數接收兩個參數,一個是函數,一個是Iterable(可迭代對象,序列)
,map
將傳入的函數func()依次作用到序列seq的每個元素,並把結果作為新的Iterator(迭代器)
返回,之后可轉為lis或其他類型t輸出。
1 #!/usr/bin/python3 2 3 def f(x): 4 return x*x 5 6 r = map(f, [ 1, 2, 3, 4, 5, 6 ]) 7 print(list(r)) 8 #由於結果r是Iterator(惰性序列),因此通過list()函數計算整個序列
reduce()
reduce(func,seq)
把一個函數作用在一個序列[x1, x2, x3, ...]
上,這個函數必須接收兩個參數,reduce()
把結果繼續和序列的下一個元素做累積計算,
意即一次取序列兩個元素放到函數,函數結果和下一個函數結果(取下兩個元素放到函數得到的函數結果)相加,依次類推。
1 #!/usr/bin/python3 2 from functools import reduce 3 4 def f(x,y): 5 return x+y 6 7 r = reduce(f, [ 1, 2, 3, 4, 5, 6 ]) 8 print(r)
filter()
filter(func,seq)
函數用於過濾序列,調用一個布爾函數func()來迭代遍歷每個seq中的元素,返回一個使func返回值為True的元素的序列
和map()
類似,filter()
也接收一個函數和一個序列。和map()
不同的是,filter()
把傳入的函數依次作用於每個元素,然后根據返回值是True
還是False
決定保留還是丟棄該元素。
篩選回文 回數是指從左向右讀和從右向左讀都是一樣的數
1 #!/usr/bin/python3 2 3 def is_palindrone(n): 4 return str(n) == str(n)[::-1] #[::-1]是倒切 從右往左 5 6 print( list( filter( is_palindrone, range(11,200) ) ) )
sorted()
排序的核心是比較兩個元素的大小。如果是數字,我們可以直接比較,但如果是字符串或者兩個dict呢?直接比較數學上的大小是沒有意義的,因此,比較的過程必須通過函數抽象出來。
sorted(seq,key=func)
函數也是一個高階函數,它可以接收一個key
函數來實現自定義的排序,例如按絕對值大小排序
不是同一種類型數據相比較,key決定比較大小的標准:
匿名函數與lambda
lambda表達式返回可調用的函數對象
1 def add(x,y):return x+y 2 sum1 = add(2,3) 3 #等價於 4 add = lambda x,y:x+y 5 add(2,3)
Python簡單的句法限制了lambda函數的定義體只能使用純表達式。即不能賦值,也不能使用while和try等Python語句
除了作為參數傳給高階函數之外,Python很少使用匿名函數
2.返回函數
把函數作為結果返回
1 #!/usr/bin/python3 2 3 def lazy_sum(*args): 4 def sum(): 5 #閉包 sum可以引用外部函數lazy_sum的參數和局部變量 6 ax = 0 7 for n in args: 8 ax = ax+n 9 return ax 10 return sum 11 12 f = lazy_sum(1, 3, 5, 7, 9) #不需要立即求和,而是在后面的代碼中根據需要計算 13 #返回的函數並沒有立刻執行,而是直到調用了f()才執行 14 print(f())
返回值與函數類型
返回的對象數目 Python實際返回的對象類型
0 None
1 object
>1 tuple
3.裝飾器
不修改原函數的定義,在代碼運行期間動態增加功能的方式(如在調用前后自動打印日志,但又不修改函數的定義),稱之為“裝飾器”(Decorator),裝飾器就是函數,借助@調用。
1 #!/usr/bin/python3 2 3 def log(func): 4 def printInfo(*arge, **kw): #*不定長參數 **關鍵字參數 5 print('call %s()' % func.__name__) #在調用func之前打印一些信息 6 return func(*arge, **kw) 7 return printInfo 8 9 #log是一個裝飾器,接收函數返回函數,借助@語法把裝飾器置於函數的定義外 10 @log #相當於執行了 now = log(now) 11 def now(): 12 print('2019-4-20') 13 14 #現在同名now()指向了新的函數,調用now()返log()中的printInfo()函數 15 print(now())
4.偏函數
當函數參數過多,需簡化時,使用 functools.partial() 可以創建一個新的函數,這個函數可以固定住原函數的部分參數
1 #!/usr/bin/python3 2 import functools 3 4 int2 = functools.partial(int, base = 2) 5 print(int2('1000000')) #現在只需傳一個序列, 不需傳指定的進制