装饰器
什么是装饰器
- 装饰器本身是函数,用来修饰其他函数,为其他函数添加附加功能
装饰函数的原则
- 不能修改函数的源代码
- 不能改变函数的调用方法
实现装饰器的知识储备
- 函数即变量
- 高阶函数
- 把一个函数名当做实际参数传递给另一个函数(在不修改函数源代码的前提下,为函数添加功能)
- 把函数名当做返回值(不修改函数的调用方式)
- 嵌套函数
高阶函数+嵌套函数=》装饰器
详细说明
首先我们创建一个函数,功能是先等待3秒,然后打印一条语句
import time #导入time模块 def print_out(): #创建函数 time.sleep(3) print('in the func print_out') print_out()#调用函数
输出的结果是
in the func print_out
我们看到成功打印出了内容。
现在我们有了一个新的需求,除了打印语句之外,我想知道运行这个函数花费了多少时间,这个该怎么做呢
我们可以改变下代码:
def print_out(): start_time = time.time() time.sleep(3) print('in the func print_out') stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) print_out()
输出的结果:
in the func print_out the func run time is 3.0000908374786377
我们通过修改源代码把新的功能添加到了函数中,但是如果有100这样的函数,我们怎么帮呢?
我们可以考虑使用装饰器完成这个工作,根据装饰器的原则我们一步一步完成代码
创建高阶函数,把print_out这个函数名传递到高阶函数里,先给函数添加功能:
import time #导入time模块 def deco(func): #定义高阶函数 print('------------------') start_time = time.time() func() stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) print('------------------') def print_out(): time.sleep(3) print('in the func print_out') deco(print_out) #调用高阶函数deco
输出结果
------------------ in the func print_out the func run time is 3.0003957748413086 ------------------
我们看到输出结果已经出现了函数运行的时间,但是有一个问题,根据代码我们发现函数的调用方式改变了,原来是print_out()调用,现在是deco(print_out),这不是我们想要看到的,我们可以使用返回函数名的方法解决这个问题
修改代码:
import time #导入time模块 def deco(func):#定义高阶函数 print('------------------') start_time = time.time() return func stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) print('------------------') def print_out(): time.sleep(3) print('in the func print_out') print_out = deco(print_out) print_out()
输出结果:
------------------
in the func print_out
这个输出是什么鬼,虽然函数的调用方式没有改变,函数的源代码也没有改变,但是功能也没用添加上去,头大。
现在是嵌套函数出场的时间了,使用嵌套函数来解决这个问题。
修改后的代码:
import time #导入time模块 def timer(func): def deco():#定义高阶函数 print('------------------') start_time = time.time() func() stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) print('------------------') return deco def print_out(): time.sleep(3) print('in the func print_out') print_out = timer(print_out) print_out()
输出结果:
------------------ in the func print_out the func run time is 3.0022478103637695 ------------------
上面的代码达到了我们的要求,没有改变源代码,没有改变调用方式,而且添加了新的功能。
但是 print_out = timer(print_out)这句看着不是很舒坦。使用@符号可以代替它,在我们要装饰的函数前面使用@timer,这样函数就被装饰了
代码如下:
import time #导入time模块 def timer(func): def deco():#定义高阶函数 print('------------------') start_time = time.time() func() stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) print('------------------') return deco @timer #print_out = timer(print_out) def print_out(): time.sleep(3) print('in the func print_out') print_out()
装饰器的说明完成了。 以上