python--装饰器

  装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。


在编程过程中我们会调用许多函数,例如:

def foo():
    print('this is foo')
foo()
def bar():
    print('this is bar')
bar()

  

但现在我们的需求是得到函数运行所需的时间:

import time
def foo():
    start = time.time()
    print("this is foo.")
    time.sleep(2)      #因为此函数运行太快所以加个延时
    end = time.time()
    print('spend %s'%(end-start))
foo()
def bar():
    start = time.time()
    print("bar..........")
    time.sleep(2)
    end = time.time()
    print('spend %s' % (end - start))
bar()

 虽然以上按要求做出来了,但是却有重复的代码,为了解决重复代码,如下:

import time
def foo():
    print('foo........')
    time.sleep(2)
def bar():
    print("bar&&&&&&&&")
    time.sleep(2)
def show_time(f):
    start = time.time()
    f()
    end = time.time()
    print('spend %s'%(end-start))
show_time(foo)
show_time(bar)
#输出:
foo........
spend 2.0001730918884277
bar&&&&&&&&
spend 2.000176429748535

  这个挺好的,但是吧,如果我们要求最后运行的函数就是本函数比如foo()而不是show_time(foo),那么就:

import time
def show_time(f):
    def wrapper():
        start = time.time()
        f()
        end = time.time()
        print('spend %s'%(end-start))
    return wrapper
def foo():
    print('foo..........')
    time.sleep(2)
foo = show_time(foo)
foo()
#输出:
foo..........
spend 2.0007383823394775

  python里有个更简便的做法,加@:

import time
def show_time(f):
    def wrapper():
        start = time.time()
        f()
        end = time.time()
        print('spend %s'%(end-start))
    return wrapper
@show_time
def foo():
    print('foo..........')
    time.sleep(2)
foo()

  带参数的被修饰函数:

import time
def show_time(f):
    def wrapper(a,b):
        start = time.time()
        f(a,b)
        end = time.time()
        print('spend %s'%(end-start))
    return wrapper
@show_time
def add(a,b):
    print(a+b)
    time.sleep(2)
add(1,2)
#输出:3
可变长加法
def show_time(f):
    def wrapper(*a,**b):
        start = time.time()
        f(*a,**b)
        end = time.time()
        print('spend %s'%(end-start))
    return wrapper
@show_time
def add(*a,**b):
    sum = 0
    for i in a:
        sum+=i
    print(sum)
    time.sleep(2)
add(1,2,4,5,6)
#输出:18

  装饰器还有更大的灵活性,例如带参数的装饰器:在上面的装饰器调用中,比如@show_time,该装饰器唯一的参数就是执行业务的函数。装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。

 

import time
def time_logger(flag=0):
    def show_time(f):
        def wrapper():
            start = time.time()
            f()
            end = time.time()
            print('spend %s'%(end-start))
            if flag :
                print('将这个操作时间写入日志')
        return wrapper
    return show_time
@time_logger(1)
def foo():
    print('foo..........')
    time.sleep(2)
foo()

  

原文地址:https://www.cnblogs.com/liang-chen/p/11563827.html