定义:
本质是函数,(装饰其他函数)就是为其他函数添加附加功能
法则:
- 不能修改被装饰函数的源代码
- 不能修改被装饰函数的调用方式
实现装饰器的知识储备
1、函数名即变量
2、高阶函数
- 把一个函数名作为实参传递给另一个函数(法则1不修改被装饰函数的源代码)
- return 返回一个函数(法则2不修改被装饰函数的调用方式)
举例如下:
import time
def bar():
time.sleep(3)
print('in the bar')
##在内存中开辟一个单元,这个内存单元的名字则为bar,存储上面的函数体
print(bar)
##打印bar函数的内存单元地址
def test2(func):
print(func) #打印func的内存单元地址
return func #返回func
##在内存中开辟一个单元,这个内存单元的名字则为test2,存储上面的函数体
b=test2(bar)
##test2(bar) 将bar作为实参传递给函数test2,那在函数test2中的局部变量func指向名字为bar的内存单元
##函数test2,第一个操作打印func的内存单元地址,也就是打印bar函数的内存单元地址
##函数test2,第二个操作返回func,也就是返回函数bar的内存单元地址
##那么b=test2(bar),先打印bar的地址,再将变量b指向函数bar的内存单元
b()
##此时执行函数b,也就是执行bar函数
3、嵌套函数
在一个函数体内定义一个函数
无参装饰器示例
import time
def timer(func): #timer(test1) func=test1
def deco(*args,**kwargs):
start_time=time.time() ##可在被装饰函数执行前添加的功能
func(*args,**kwargs)
stop_time = time.time() ##可在被装饰函数执行后
print("the func run time is %s" %(stop_time-start_time))
##在内存中开辟一个单元,这个内存单元的名字则为deco,存储上面的函数体
return deco##返回函数deco
##在内存中开辟一个单元,这个内存单元的名字则为timer,存储上面的函数体
@timer #test1=timer(test1)
def test1(n):
time.sleep(n)
print('Hi~')
##@timer装饰器的语法糖,用于简化代码,装饰器的语法糖需要写在被装饰函数的上一行
##@为特殊用法,是将后面定义函数进行高阶化,本次效果等同于test1=timer(test1)
##timer(test1) 将test1作为实参传递给函数timer,在timer函数中将局部变量名func指向名为test1的内存单元
##函数timer,第一个操作在内存中开辟一个单元,这个内存单元的名字则为deco,存储deco的函数体;第二个操作返回返回deco
##那么test1=timer(test1),先定义一个函数deco,再把这个函数返回,相当于将test1名字指向deco的存储单元,而在deco的单元中已经存储了test1原来的函数体
test1(3)
有参装饰器实例
import time
def timer2(t):##再包一层嵌套函数,用于接受装饰器的参数。
def timer(func):
def inner(*args,**kwargs):
start=time.time()
ret = func(*args,**kwargs)
delta =time.time()-start
if delta>t:
print('消耗时间:%s'%(delta))
return ret
return inner
return timer
@timer2(2) #add=timer2(5)(add),timer2(5)==>timer函数,在该函数中t=5
def add(x,y):
time.sleep(3)
return x+y
print(add(4,5))