Python語言之高階函式
Python語言之高階函式
前言
人生苦短,我用Python。
一、閉包
Python函式是支援巢狀的。如果在一個內部函式中對外部函式作用域(非全域性作用域)的變數進行引用,那麼內部函式就會被稱為閉包。閉包需要滿足如下3個條件:
-
存在於兩個巢狀關係的函式中,並且閉包是內部函式;
-
內部函式引用了外部函式的變數(自由變數);
-
外部函式會把內部函式的函式名稱返回。(不帶括號)
def nth_power(exponent): def exponent_of(base): return base ** exponent return exponent_of # 返回值是 exponent_of 函式 square = nth_power(2) # 計算一個數的平方,傳遞exponent為2 cube = nth_power(3) # 計算一個數的立方,傳遞exponent為3 print(square(2)) # 計算 2 的平方,傳遞base為2 print(cube(2)) # 計算 2 的立方,傳遞base為2 print(nth_power(2)(4))# 直接計算 2 的4次方
為什麼使用閉包?
引用資料:
二、裝飾器
裝飾器的概念
假設我們已經開發了一個本有的函式,後續可能會增加臨時的需求,例如插入日誌,我們可以增加一個包裹函式,由它來負責這些額外的需求,這個包裹函式就是裝飾器 。
裝飾器主要應用在如下場景:
- 引入日誌;
- 函式執行時間統計;
- 執行函式前預備處理;
- 執行函式後清理功能;
- 許可權校驗;
- 快取。
裝飾器是一個函式,它需要接收一個被修飾的函式作為引數。例如,有如下一個裝飾器函式:
def w1(func): print('正在裝飾') def inner(): print('正在驗證許可權') func() return inner
-
裝飾器是個巢狀函式
-
內部函式是一個閉包
-
外部函式接收的是被修飾的函式(func)
通過在函式定義的前面新增@符號和裝飾器名,實現裝飾器對函式的包裝。給f1函式加上裝飾器,示例如下:
@w1
def f1():
print('f1')
呼叫f1時候,程式會自動編譯生成呼叫裝飾器函式的程式碼,等價於:
f1 = w1(f1)
多個裝飾器
多個裝飾器應用在一個函式上,是一個巢狀的關係,呼叫順序是從下至上,再從上至下。
def w1(func): print('正在裝飾w1') def inner(): print('正在驗證許可權w1') func() return inner
def w2(func):
print('正在裝飾w2')
def inner2():
print('正在驗證許可權w2')
func()
return inner2
@w1
@w2
def f1():
print('f')
#f1() #先註釋掉,觀察執行結果
#相當於w1(w2(f1))()
裝飾有引數的函式
def w1(func):
def inner(a,b):
print('開始驗證許可權')
func(a,b)
return inner
@w1
def test(a,b):
print('a=%d,b=%d'%(a,b))
test(1,2)
裝飾帶有返回值的函式
def func(functionName):
print('進入裝飾器')
def func_in():
print('呼叫被裝飾函式')
return functionName()
return func_in
@func
def test():
return 'itheima'
print(test())
帶有引數的裝飾器
如果給裝飾器新增引數,需要增加一層包裝,先傳遞引數,然後再傳遞函式名。示例程式碼如下:
def func_arg(args):
def func(functionName):
def func_in():
print('記錄日誌:%s'%args)
functionName()
return func_in
return func
@func_arg('這是一條日誌')
def fun1():
print('記錄完成')
fun1()
三、裝飾器常見Python內建函式
map函式
map函式會根據提供的函式對指定的序列做對映。
map函式的定義如下:
map(function, iterable,…)
第1個引數是函式的名稱;第2個引數表示支援迭代的容器或者迭代器。
map函式的作用是以引數序列中的每個元素分別呼叫function函式,把每次呼叫後返回的結果儲存為物件。
func = lambda x:x+2
result = map(func, [1,2,3,4,5])
print(list(result))
執行過程:
filter函式
filter函式會對指定序列執行過濾操作。
filter函式的定義如下:
filter(function,iterable)
第1個引數可以是函式的名稱;第2個引數表示的是序列、支援迭代的容器或迭代器。
func = lambda x:x%2
result = filter(func, [1, 2, 3, 4, 5])
print(list(result))
執行過程:
reduce函式
reduce函式會對引數序列中的元素進行迭代運算。
reduce函式的定義如下:
reduce(function, iterable[, initializer])
- function是一個帶有兩個引數的函式;
- iterable是一個可迭代物件;
- initializer表示固定的初始值。
函式將一個數據集合(連結串列,元組等)中的所有資料進行下列操作:用傳給 reduce 中的函式 function(有兩個引數)先對集合中的第 1、2 個元素進行操作,得到的結果再與第三個資料用 function 函式運算,最後得到一個結果。
reduce(function, iterable[, initializer])
from functools import reduce
func = lambda x,y:x+y
result = reduce(func, [1, 2, 3, 4, 5])
print(result)
注意:function函式不能為None。
在Python 3中,reduce函式已經被從全域性名字空間裡面移除了,它現在被放置在fucntools模組中,使用時需要先引入,格式如下:
from functools import reduce