概述
顾名思义,所谓装饰器就是对原有的对象做一些装饰,也就是给已有的对象添加一些功能。
假如我现在想在函数运行时输出一些信息
小学水平
1 | def running(func): |
输出1
2`my_sum` is running...
I cat't sum right now!
要使用装饰器,先得定义一个装饰器函数,然后在需要装饰的函数的前一行使用@
符号加上装饰器名称
。
在这里的效果等效于running(my_sum)(),不过看起来有点别扭。
注意:一旦通过@running
装饰了函数,不管被装饰函数是否运行,python解释器都会执行一遍running
函数。
中学水平
上一个装饰器用起来还行,但是有一个致命的问题,它不能装饰带参数的函数。所以我们在装饰器内部定义_wrapper
函数,并返回它。这个函数接收所有位置参数*args
,和关键字参数*kwargs
,在_wrapper
内部执行func(*args, **kwargs)
。
1 | def running(func): |
输出1
2
3`my_sum` is running...
3
_wrapper
这也是python中最普通的装饰器,假如需要在my_sum
运行之后添加一些功能,则可以改成这样。1
2
3
4
5
6
7
8
9
10import time
def running(func):
def _wrapper(*args, **kwargs):
start = time.time()
print '`%s` is running...' % func.__name__
_result = func(*args, **kwargs)
print 'run `%s` takes %s seconds' % (func.__name__, time.time()-start)
return _result
return _wrapper
大学水平
上一个装饰器也有一个问题,就是经过装饰的my_sum.__name__
变成了_wrapper
。
这个问题可以通过python内置的functools.wraps
解决,这个装饰器对原函数的一些属性进行了复制。
1 | import time |
输出1
2
3
4`my_sum` is running...
run `my_sum` takes 1.0 seconds
3
my_sum