1、装饰器的定义
装饰器本质上就是一个函数,功能是为其他函数添加功能
装饰器的原则:
- 不修改被装饰函数的源代码
- 不修改被装饰函数的调用方式
2、装饰器的知识储备
先声明一点:装饰器=高阶函数+函数嵌套+闭包
2.1、高阶函数
定义:
- 函数的参数是一个函数
- 函数的返回值是一个函数
2.2、嵌套函数
定义:
- 在一个函数的内部又定义一个函数
注:在嵌套函数中外部的函数称为外函数,在函数内部定义的函数称为内函数
2.3、闭包
定义:
- 内函数调用外函数的临时变量
- 外函数的返回值是内函数的引用
代码示例:
def test(a, b):
def test2():
print(a + b)
return test2
res = test(1, 2)
res() # 相当于调用test2()
3、装饰器
3.1、装饰器的基本语法格式
通过上面已经知道了 装饰器=高阶函数+函数嵌套+闭包,下面来实现一下装饰器
使用装饰器统计函数test运行的时间
import time
def timer(func):
'计算程序运行时间的函数'
def count():
start_time = time.time()
func()
end_time = time.time()
print("运行的时间是%s" % (end_time - start_time))
return count
@timer # @timer就是相当与执行了timer(test)()
def test():
time.sleep(3)
print("函数test运行结束")
运行时间:
函数test运行结束
运行的时间是3.0005695819854736
3.2、函数加上返回值
当我们在test函数中加上一个return返回值的时候会发现在调用test函数的时候并没有返回值,原因是函数test是在装饰器函数的内函数中运行的,在内函数中并没有return值,修改如下:
import time
def timer(func):
def count():
start_time = time.time()
res = func()
print(res)
end_time = time.time()
print("运行的时间是%s" %(end_time - start_time))
return count
@timer
def test():
time.sleep(3)
print("函数test运行结束")
return "这是test的返回值"
test()
3.3、函数加上参数
当对test函数加上参数的时候会发现代码报错,原因是在装饰器的内函数中我们并没有给定形参,导致test在内函数中运行时无法接收相应的实参;修改如下:
import time
def timer(func):
def count(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
print(res)
end_time = time.time()
print("运行的时间是%s" %(end_time - start_time))
return count
@timer
def test(name, age):
time.sleep(3)
print("函数test运行结束")
print("名字 【%s】,年龄【%s】" %(name, age))
return "这是test的返回值"
test("xiaoming", 20)
运行结果:
函数test运行结束
名字 【xiaoming】,年龄【20】
这是test的返回值
运行的时间是3.0006966590881348
3.4、给装饰器函数加上参数
如果需要给用户选择test函数是否要统计运行时间的话就要给装饰器添加一个参数,判断是否要统计test运行的时间;可使用闭包
情况1:需要进行运算时间的统计
import time
def auth(para = True):
def timer(func):
def count(*args, **kwargs):
if para == True:
start_time = time.time()
res = func(*args, **kwargs)
print(res)
end_time = time.time()
print("运行的时间是%s" %(end_time - start_time))
else:
func(*args, **kwargs)
return count
return timer
@auth(para=True)
def test(name, age):
time.sleep(3)
print("函数test运行结束")
print("名字 【%s】,年龄【%s】" %(name, age))
return "这是test的返回值"
test("xiaoming", 20)
运行结果:
函数test运行结束
名字 【xiaoming】,年龄【20】
这是test的返回值
运行的时间是3.0004258155822754
情况2:不需要进行运算时间的统计
import time
def auth(para = True):
def timer(func):
def count(*args, **kwargs):
if para == True:
start_time = time.time()
res = func(*args, **kwargs)
print(res)
end_time = time.time()
print("运行的时间是%s" %(end_time - start_time))
else:
func(*args, **kwargs)
return count
return timer
@auth(para=False)
def test(name, age):
time.sleep(3)
print("函数test运行结束")
print("名字 【%s】,年龄【%s】" %(name, age))
return "这是test的返回值"
test("xiaoming", 20)
运行结果:
函数test运行结束
名字 【xiaoming】,年龄【20】
网友评论