装饰器

什么是装饰器

  • 装饰器本身是函数,用来修饰其他函数,为其他函数添加附加功能

装饰函数的原则

  1. 不能修改函数的源代码
  2. 不能改变函数的调用方法

实现装饰器的知识储备

  1. 函数即变量
  2. 高阶函数
    1. 把一个函数名当做实际参数传递给另一个函数(在不修改函数源代码的前提下,为函数添加功能)
    2. 把函数名当做返回值(不修改函数的调用方式)
  3. 嵌套函数

高阶函数+嵌套函数=》装饰器

 

详细说明

首先我们创建一个函数,功能是先等待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()

装饰器的说明完成了。 以上

 

posted @ 2019-10-10 09:15  goldtree358  阅读(122)  评论(0)    收藏  举报