為什么要使用?
使用裝飾器使代碼變得整潔同窘,并且能解決硬編碼問題锈至,使用起來也很方便,但是理解起來相對(duì)沒那么容易驹愚,因此寫下這篇文章加深理解远搪。下面以記錄日志的功能作為裝飾器的講解:
原始硬編碼版
下面的logit作為裝飾器,但是它只能裝飾有兩個(gè)參數(shù)的函數(shù)逢捺,因此是硬編碼的谁鳍。
def logit(func):
def decorator(a, b):
print("func %s is calling " % func.__name__)
return func(a, b)
return decorator
@logit()
def my_add(a, b):
return a+b
my_add(1, 49)
可變參數(shù)版
使用*args, **kwargs將上述的硬編碼去除,使得裝飾器能裝飾不同的函數(shù)
def logit(func):
def decorator(*args, **kwargs):
print("func %s is calling " % func.__name__)
return func(*args)
return decorator
wraps通用版
輸出my_add.name發(fā)現(xiàn)函數(shù)的名稱改變了劫瞳,不是我們想要的my_add倘潜,因此使用wraps改造
print(my_add.__name__)
from functools import wraps
def logit(func):
@wraps(func)
def decorator(*args, **kwargs):
print("func %s is calling " % func.__name__)
return func(*args)
return decorator
自定義參數(shù)版
有時(shí)候需要向裝飾器來傳遞參數(shù),例如不同的函數(shù)需要不同的日志文件時(shí):
def logit(log_name="add.log"):
def decorator(func)
@wraps(func)
def wrapper(*args, **kwargs):
log_str = "func %s is calling " % func.__name__
print(log_str)
with open(log_name, "a") as log_file:
log_file.write(log_str)
return func(*args)
return wrapper
return decorator