定義:在函數(shù)調(diào)用前后增加功能母怜,但又不修改原函數(shù)的定義,這種在代碼運行期間動態(tài)增加功能的方式缚柏,稱之為“裝飾器”
接受一個函數(shù)作為參數(shù)苹熏,并返回一個函數(shù)
模板如下:
def module(func):
def wrapper(*args, **kw):
print 'call deractor function.'
return func(*args, **kw)
return wrapper
實例:提醒使用者使用的函數(shù)將廢棄
decorator裝飾之后的函數(shù),它們的__name__已經(jīng)從原來的test變成了deprecated币喧, 返回的那個wrapper函數(shù)名字就是wrapper
轨域,所以,需要把原始函數(shù)的__name__等屬性復制到test()函數(shù)中, 即_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
其實相當于執(zhí)行語句 deprecated(test)()
def test():
print 'only for test'
deprecated(test)()
#result
*WARN* Keyword "test" will deprecated
only for test
接受一個傳參作為參數(shù)杀餐,并返回一個函數(shù)
模板如下:
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
實例:提醒使用者使用的函數(shù)將廢棄, 替換成其他函數(shù)
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
其實相當于執(zhí)行語句 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
常用總結(jié)
1.設(shè)置函數(shù)超時
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.設(shè)置函數(shù)運行多次
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!