关于python的装饰器decorator

jling 2019-06-26

刚接触python,看到装饰器相关的内容花了不少时间理解,参考了一些博客,这里做一些总结。

先定义一个简单的函数foo

def foo():
    print 'call foo()'

现在我们想要计算次函数执行的时间,于是修改代码如下

import time

def foo():
    start = time.clock()
    print 'call foo()'
    end = time.clock()
    print 'using time:',end - start

思考一下,这样做能够实现,可是如果我还想知道另一个foo_1的运行时间,那我只能把上面新增加的代码复制到foo_1这个函数里面,十分麻烦,能不能够不要改变原本的函数,即计算时间的代码不加在本来的函数里面。

这应该不难,很容易想到可以这样写

import time
 
def foo():
    print 'call foo()'
 
def cal_time(func):
    start = time.clock()
    func()
    end =time.clock()
    print 'using time:', end - start
 
cal_time(foo)

这样,如果还需要计算函数foo_1的时间,只需要cal_time(foo_1)就好了。

但是,这样其实改变了函数原本的调用方式,开始我们是这样调用foo()
现在是cal_time(foo)

那么如果现在需要修改foofoo_plus,我就必须更改n处调用了foo的代码!

还有更好的实现方式吗?能否使调用foo()产生时调用cal_time(foo)的效果?
可以想到,把cal_time(foo)的返回值赋给foo,看看下面的实现

import time
 
def foo():
    print 'call foo()'
 
# 定义一个计时器,传入一个函数,并返回另一个附加了计时功能的方法
def cal_time(func):
     
    # 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装
    def wrapper():
        start = time.clock()
        func()
        end =time.clock()
        print 'using time:', end - start
     
    # 将包装后的函数返回
    return wrapper
 
foo = cal_time(foo)
foo()

这样便无需改变原函数及其调用,想计算函数foo的用时,在函数调用foo()前,加上foo = cal_time(foo)即可。

用Python提供的语法糖来降低字符输入量。

import time
 
def cal_time(func):
    def wrapper():
        start = time.clock()
        func()
        end =time.clock()
        print 'using time:', end - start
    return wrapper
 
@cal_time               #定义函数时加上这一行与另外写foo = cal_time(func):完全等价
def foo():
    print 'call foo()'
 
foo()

如有错漏,请指正

参考资料:
1.http://www.cnblogs.com/rollen...
2.https://www.liaoxuefeng.com/w...

相关推荐