装饰器作用与原理

装饰器是python的一个神器,它赋予函数在不修改自身代码的情况下改变自身行为的能力,装饰器的基本原理是python函数可以接受一个函数作为参数并返回一个函数。

1. 装饰器的作用

当你编写了一段程序,发现程序运行的很慢,调试过程中,你需要知道程序执行过程中每一个函数的执行时间,以此来确定哪里需要优化性能,通常的做法是在函数开始的时候记录一次时间,在函数结束的时候记录一次时间,这两个时间的差值就是函数的执行时间。

这样做的确可以实现目标,但却有一个缺点。你不得不修改函数,如果函数调用很多,你不得不一一修改,结束优化后,你不得不删除掉那些添加的用来记录时间的代码。

下面是一个普通的函数

def test_decorator():
    time.sleep(1)
    print("执行函数test_decorator")

如果按照刚才讲的方法,你需要把函数修改成这样

def test_decorator():
    t1 = time.time()
    time.sleep(1)
    print("执行函数test_decorator")
    t2 = time.time()
    print("执行耗时" + str(t2 - t1))

修改以后,代码变得臃肿,而且结束优化后,你要删除掉刚才所添加的3行代码

2. 用装饰器来改变函数行为

现在,我们写一个简单的装饰器,改变函数test_decorator的行为,让它具备记录自身执行时间的能力,装饰器代码如下

def cost(func):
    def warpper():
        t1 = time.time()
        res = func()
        t2 = time.time()
        print(func.__name__ + "执行耗时" +  str(t2-t1))
        return res
    return warpper

cost 是一个函数,入参func是一个函数,返回值warpper是一个函数, 使用非常简单

def test_decorator():
    time.sleep(1)
    print("执行函数test_decorator")


test = cost(test_decorator)
print(test)
test()

输出结果为

<function cost.<locals>.warpper at 0x118a31840>
执行函数test_decorator
test_decorator执行耗时1.0051071643829346

将test_decorator作为参数传给cost函数,cost函数返回的warpper也是一个函数,而这个函数里执行了test_decorator并且记录了函数的执行时间,对于test_decorator这个函数,我们没有对它做任何改变,但却得到了它的执行时间。

上面的实例,并不是工作中使用的方法,我创建了一个test变量,并将cost的返回值赋值给他,是为了让你清晰的看到装饰器是如何工作的,装饰器的工作原理就是将被装饰的函数放入到一个新的函数中执行,这个新的函数是你自己编写的,因此,你可以做任意你想做的事情来实现自己想要的功能却不需要改变被装饰的函数。

实际工作中,我们这样使用装饰器

@cost
def test_decorator():
    time.sleep(1)
    print("执行函数test_decorator")


test_decorator()

使用@cost装饰一个test_decorator等价于test = cost(test_decorator),好处时无需再定义一个变量test,当你不需要记录函数的执行时间时,只需要移除@cost即可

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案