定义:在函数调用前后增加功能,但又不修改原函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”
接受一个函数作为参数,并返回一个函数
模板如下:
def module(func):
def wrapper(*args, **kw):
print 'call deractor function.'
return func(*args, **kw)
return wrapper
实例:提醒使用者使用的函数将废弃
decorator装饰之后的函数,它们的__name__已经从原来的test变成了deprecated, 返回的那个wrapper函数名字就是wrapper
,所以,需要把原始函数的__name__等属性复制到test()函数中, 即_wrapped.func_name = func.func_name
def deprecated(func):
def _wrapped(*args, **kwargs):
print '*WARN* Keyword "%s" will deprecated' % func.__name__
return func(*args, **kwargs)
_wrapped.func_name = func.func_name
return _wrapped
@deprecated
def test():
print 'only for test'
test()
#result
*WARN* Keyword "test" will deprecated
only for test
其实相当于执行语句 deprecated(test)()
def test():
print 'only for test'
deprecated(test)()
#result
*WARN* Keyword "test" will deprecated
only for test
接受一个传参作为参数,并返回一个函数
模板如下:
def module(arg):
def decorator(func):
def _wrapped(*args, **kwargs):
print 'call deractor function, get a argument %s' % arg
return func(*args, **kw)
return _wrapped
return decorator
实例:提醒使用者使用的函数将废弃, 替换成其他函数
def deprecated(replacement):
def deprecated(func):
warning_msg = '*WARN* Keyword "%s" is deprecated, use "%s"' % (func.func_name, replacement)
def _wrapped(*args, **kwargs):
print(warning_msg)
return func(*args, **kwargs)
_wrapped.func_name = func.func_name
return _wrapped
return deprecated
@deprecated('for_test')
def test():
print 'only for test'
test()
#result
*WARN* Keyword "test" is deprecated, use "for_test"
only for test
其实相当于执行语句 deprecated('for_test')(test)()
def test():
print 'only for test'
deprecated('for_test')(test)()
#result
*WARN* Keyword "test" is deprecated, use "for_test"
only for test
常用总结
1.设置函数超时
import signal
import time
def set_timeout(timeout):
def decorator(func):
def handle(signum, frame):
raise RuntimeError("Run function %s time out" % func.func_name)
def wrapper(*args, **kwargs):
signal.signal(signal.SIGALRM, handle)
signal.alarm(timeout)
result = func(*args, **kwargs)
signal.alarm(0)
return result
wrapper.func_name = func.func_name
return wrapper
return decorator
@set_timeout(3)
def test():
while True:
time.sleep(1)
print '111'
test()
#result
111
111
Traceback (most recent call last):
File "/home/fantao/workspace/nbs/test.py", line 25, in <module>
test()
File "/home/fantao/workspace/nbs/test.py", line 11, in wrapper
result = func(*args, **kwargs)
File "/home/fantao/workspace/nbs/test.py", line 22, in test
time.sleep(1)
File "/home/fantao/workspace/nbs/test.py", line 7, in handle
raise RuntimeError("Run function %s time out" % func.func_name)
RuntimeError: Run function test time out
2.设置函数运行多次
import functools
def run_times(times):
def decorator(func):
counter = {'times': 0}
@functools.wraps(func)
def wrapper(*args, **kw):
for _ in range(times):
func(*args, **kw)
return wrapper
return decorator
@run_times(3)
def test():
print 'hello, world!'
test()
#result
hello, world!
hello, world!
hello, world!