目的:
假設我們想要對某些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")) 沒有被執行