1.1 装饰器
1.装饰器是什么?
装饰器简单来说就是在不改变代码的前提下,使代码拓展额外的功能。也就是修改其他代码功能的函数。(采用了闭包和把函数作为参数)
2.初始装饰器
1.将函数作为变量传递给另一个函数
我们定义两个函数,funA() 和 funB(),将函数funB()作为参数传递给函数funA()
def funA(fun): #参数为函数的引用(函数的函数名就是函数的引用)
print("start.....")
fun() #添加一个小括号来调用一个函数
print("end.....")
def funB():
print("正在调用funB")
funA(funB) #将函数funB()作为参数传递给函数funA()
start.....
正在调用funB
end.....
为了更加直观地看到调用过程,我们给函数运行加个延迟,这里使用time库里的sleep函数和time函数来进行。
import time #引入time库
def funA(fun):
print("start.....")
start = time.time()
fun()
end = time.time()
print("end.....")
print("程序一共运行了{:.2f}秒".format(end - start))
def funB():
time.sleep(3) #使运行延迟3秒
print("正在调用funB")
funA(funB)
start.....
正在调用funB
end.....
程序一共运行了3.02秒
2.语法糖
如果每次想要实现不同效果,都要修改原有的代码的话,会使我们写起程序来很麻烦,这时候就轮到装饰器来发挥作用了。让我们在调用funB()的时候自觉调用funA()。
import time
def funA(fun):
print("start.....")
start = time.time()
fun()
end = time.time()
print("end.....")
print("程序一共运行了{:.2f}秒".format(end - start))
@funA # funA(funB)
def funB():
time.sleep(3)
print("正在调用funB")
start.....
正在调用funB
end.....
程序一共运行了3.03秒
这里的@funA 其实就是语法糖,它的实质写法是:funA(funB),我们将其赋值给一个变量进行输出会得到一样的结果。
import time
def funA(fun):
print("start.....")
start = time.time()
fun()
end = time.time()
print("end.....")
print("程序一共运行了{:.2f}秒".format(end - start))
def funB():
time.sleep(3)
print("正在调用funB")
a = funA(funB) # @funA
start.....
正在调用funB
end.....
程序一共运行了3.01秒
使用装饰器不用去修改原来的代码,只需在函数上面加上一个@函数名即可,对于语法糖,他只是一种特殊的语法,可以使程序变得更加直观和简洁。
3.多层装饰器
Python支持多个装饰器作用在一个函数上,举个例子
def outsideA(fun):
print("我是外部的A")
def inner():
x = fun()
sum = x + 1
print("我是内部的A,此时的结果为:",sum)
return sum
return inner
def outsideB(fun):
print("我是外部的B")
def inner():
x = fun()
sum = x * 5
print("我是内部的B,此时的结果为:",sum)
return sum
return inner
def outsideC(fun):
print("我是外部的C")
def inner():
x = fun()
sum = x * x
print("我是内部的C,此时的结果为:",sum)
return sum
return inner
# 相当于outsideA(outsideB(outsideC(test)))
@outsideA
@outsideB
@outsideC
def test():
print("我是test")
return 2
print("结果为:",test())
程序的运行结果为:
我是外部的C
我是外部的B
我是外部的A
我是test
我是内部的C,此时的结果为: 4
我是内部的B,此时的结果为: 20
我是内部的A,此时的结果为: 21
结果为: 21
从得出的结果我们能看到,此时程序的执行顺序是先执行outsideC函数的外部代码,接着执行outsideB、outsideA函数的外部代码,然后分别执行outsideC、outsideB、outsideA的内部代码。
4.带参数的语法糖
调用一个函数,相当于调用这个函数的引用
import time
#采用了闭包和把函数作为参数 就是装饰器
def logger(msg):
def time_master(func):
def call_func():
start = time.time()
func()
stop = time.time()
print(f"一共耗费了{(stop - start):.2f} 秒。")
return call_func
return time_master
@logger(msg="A") #这里是语法糖 具体写法是 funA = logger(msg="A")(funA) (传入两个参数,一个给logger() 一个给time_master())
def funA():
time.sleep(2)
print("正在调用funA...")
@logger(msg="B")#这里是语法糖 具体写法是 funB = logger(msg="B")(funB)
def funB():
time.sleep(2)
print("正在调用funB...")
funA()
funB()
正在调用funA...
一共耗费了2.02 秒。
正在调用funB...
一共耗费了2.02 秒。
这就是对于装饰器内容的介绍,欢迎补充!