目的:
假設我們想要對某些function的回傳值做一個簡單的處理:
如果回傳值昰list且指有一個元素就直接取出(不放在list裡面)
def unpack_list_for_one_item(fn):
"unpack list for one item, if fn return ['5.1'] than return '5.1'"
def decorator(*args, **kwargs):
fnRet = fn(*args, **kwargs)
if not isinstance(fnRet, list):
raise TypeError("The decorator-unpack_list_for_one_item input fn{0}'s result shall be list type".format(fn))
return fnRet[0] if 1==len(fnRet) else fnRet
return decorator
用法:
@unpack_list_for_one_item
def major(self):
....
@unpack_list_for_one_item
def minor(self):
....
@unpack_list_for_one_item
def patPath(self):
....
解說:
1. decorator如果沒有額外參數input和output都是function
2. decorator即使沒有被呼叫也會被run過(第一層),且在main之前就被run過,如下:
#!/usr/bin/python3
from functools import wraps, partial
import logging
def logged(func):
print ("%r %s" % (locals(), "0"))
def innerDecorate(*args, **kwargs):
print ("%r %s" % (locals(), "1"))
return func
return innerDecorate
@logged
def add(x, y):
return x + y
注意, add並沒有被呼叫, 但結果如下:
{'func': <function add at 0x7f6798c77170>} 0
這表示 print ("%r %s" % (locals(), "0")) 有被執行
並且注意 print ("%r %s" % (locals(), "1")) 沒有被執行
但注意我們只是對func加上decorator
那如果是有參數的decorator會如何?
#!/usr/bin/python3
from functools import wraps, partial
import logging
def logged(level, name=None, message=None):
print ("%r %s" % (locals(), "0"))
def decorate(func):
logname = name if name else func.__module__
log = logging.getLogger(logname)
logmsg = message if message else func.__name__
print ("%r %s" % (locals(), "1"))
@wraps(func)
def wrapper(*args, **kwargs):
print ("%r %s" % (locals(), "2"))
log.log(level, logmsg)
return func(*args, **kwargs)
return wrapper
return decorate
@logged(logging.DEBUG)
def add(x, y):
return x + y
注意,一樣add並沒有被呼叫, 但結果如下:
{'message': None, 'level': 10, 'name': None} 0
{'message': None, 'logmsg': 'add', 'func': <function add at 0x7f8c9f649710>, 'logname': '__main__', 'name': None, 'log': <logging.Logger object at 0x7f8c9f66db10>, 'level': 10} 1
這表示 print ("%r %s" % (locals(), "0")) / print ("%r %s" % (locals(), "1")) 有被執行
並且注意 print ("%r %s" % (locals(), "2")) 沒有被執行