本文介紹:高階函式,嵌套函式,以及由前面兩個組成的裝飾器
一、高階函式:以下兩種情況都是高階函式
1、將函式名當成引數傳遞給另外一個函式(作用:不修改被傳遞函式源代碼就可以添加新功能):
import time
def a():
time.sleep(1)
print("This is A funciton...")
# b函式相當于給a函式附加了一個計算時間的功能,但未修改a的源代碼
def b(func):
print(func) # 列印func的記憶體地址
start_time = time.time()
func() # 呼叫a()
end_time = time.time()
print("a函式運行時間為:%s秒" % (end_time - start_time))
b(a) # 將a函式當成一個變數傳遞給b
2、將函式名當成回傳值回傳給另外一個函式(作用:不修改被傳遞函式呼叫方式就可以添加新功能):
import time
def a1():
time.sleep(1)
print("This is A1 funciton...")
# b1函式相當于給a1函式附加了一個計算時間的功能,但未修改a的源代碼,也未修改a1的呼叫方式
def b1(func):
start_time = time.time()
func() # 呼叫a()
end_time = time.time()
print("a函式運行時間為:%s秒" % (end_time - start_time))
return func
a1 = b1(a1) # 將a1函式當成一個變數傳遞給b1
a1() # 呼叫未改變a1的呼叫方式,依然是a1()呼叫,只不過此時的a1已經通過b1裝飾過了,
二、嵌套函式:在函式內部定義一個新的函式,注意:函式內部根據就近原則一層層往外尋找變數
x = 0
def grandpa():
x = 1
def dad():
x = 2
def son():
x = 3
print(x)
son()
dad()
grandpa()
三、裝飾器:
1、定義:在不修改函式代碼和呼叫方式的前提下對該函式實作新功能的編程范式,形式上是利用高階和嵌套函式的特性,高階函式 + 嵌套函式 = 裝飾器,
所以裝飾器本質上是一個未其他函式添加新功能的函式,而且不破壞原有代碼,
2、原則:
a、不能修改被裝飾函式的代碼,此項可以防止修改以后對原來的程式邏輯造成影響
b、不能修改被修飾函式的呼叫方式,比如原來是test()這樣呼叫的,不能改成test(引數1)或者改名成test2()呼叫,這也是為了讓原來的舊代碼邏輯不會出現問題導致程式運行失敗,
c、綜上所述,也就是說被裝飾的函式感覺不到裝飾器的存在,裝飾器是透明的,
3、如何實作裝飾器?
a、函式也是一個變數,函式名是變數名,函式執行體就是具體的函式值,所以將函式名賦值給別的函式,在別的函式內部就可以直接使用該函式,
b、單層裝飾器:將函式名當成變數傳遞給另外一個函式,以達到裝飾添加新功能的目的,
def timer(func):
def deco(*args,**kwargs): #這是一個嵌套函式,將*args和**kwargs可以允許外界傳入任意個數的位置和關鍵詞引數進來
start_time = time.time()
func(*args,**kwargs)
stop_time = time.time()
print("the func run time is %s" % (stop_time - start_time))
return deco
@timer #@timer標簽就相當于這句話 test1 = time(test1) 將test1函式變數名傳給裝飾器
def test1():
time.sleep(1)
print("This is test1")
@timer # test2 = time(test2)
def test2(name,age):
time.sleep(2)
print("This is %s age:%d"%(name,age))
test1()
test2("test2",23)
c、通過嵌套函式兩層裝飾器,可以讓裝飾器傳遞引數
def outside(arg_type):
def inside(func):
def deco(*args, **kwargs):
return_valuehttps://www.cnblogs.com/tangwei-fuzhou/p/= ""
if arg_type == "1":
print("加載功能1")
return_value = https://www.cnblogs.com/tangwei-fuzhou/p/func(*args, **kwargs)
print("加載功能2")
elif arg_type == "2":
print("加載功能3")
return_value = https://www.cnblogs.com/tangwei-fuzhou/p/func(*args, **kwargs)
print("加載功能4")
else:
return_value = https://www.cnblogs.com/tangwei-fuzhou/p/func(*args, **kwargs)
print("加載功能5")
return return_value # 這個回傳值可以讓被裝飾的func函式的回傳值傳到外面
return deco
return inside
@outside(arg_type="1") # 在打標簽裝飾的同時,還可以傳遞引數給外層outside
def test1():
print("This is test1")
return "test1"
@outside(arg_type="2")
def test2():
print("This is test2")
return "test2"
@outside(arg_type="3")
def test3(1,2):
print("This is test3")
return "test3"
# test1,test2和test3的的呼叫方式和其內部代碼都未改變,但是通過裝飾器卻添加了新功能
print(test1())
print(test2())
print(test3())
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/161029.html
標籤:Python
下一篇:python中有數學功能的函式
