裝飾器讓你在?個函數(shù)的前后去執(zhí)?代碼达布。
封裝?個函數(shù), 并且?這樣或者那樣的?式來修改它的?為虾标,這就是裝飾器所做的事情蔓腐。
列如:
from functools import wraps
def a_new_decorator(a_func):
? ? @wraps(a_func)
????def wrapTheFunction():
? ? ? ? print("I am doing somethings before executing a_func")
? ? ? ? a_func()
? ? ? ? print("I am doing somethings after executing?a_func")
? ? retun wrapTheFunction
@a_new_decorator
def a_function():
? ? print("I am the function")
a_function()
print(a_function.__name__)? #可以試著去掉@wraps再執(zhí)行看看
注意: @wraps接受?個函數(shù)來進?裝飾, 并加?了復制函數(shù)名稱刁品、 注釋?檔泣特、 參數(shù)列表等等的功能。 這可以讓我們在裝飾器??訪問在裝飾之前的函數(shù)的屬性挑随。
1状您、裝飾器在Flask和Django等web框架和日志中使用比較頻繁,舉個日志的例子
from functools import wraps
def logit(func):
? ? @wraps(func)
? ? def with_logging(*args,**kwargs):
? ? ? ? print(func.__name__ + " was called")
? ? ? ? return func(*args,**kwargs)
? ? return with_logging
@logit
def addition_func(x):
? ? return (x+x)
result = addition_func(4)
2兜挨、在函數(shù)中嵌入裝飾器膏孟,構建帶參數(shù)的裝飾器
from functools import wraps
def logit(logfile="out.log")
? ? def logging_decorator(func):
? ? ? ? @wraps
? ? ? ? def wrapped_function(*args,**kwargs):
? ? ? ? ? ? log_string = func.__name__ + "was called"
? ? ? ? ? ? print(log_string)
? ? ? ? ? ? with open(logfile,'a') as opened_file:
? ? ? ? ? ? ? ? opened_file.write(log_string + '\n')
? ? ? ? return wrapped_function
? ? return logging_decorator
@logit()
def func1():
? ? pass
執(zhí)行func1,會生成out.log的日志文件
@logit(logfile="func2.log")
def func2():
? ? pass
執(zhí)行func2拌汇,會生成func2.log的日志文件
3柒桑、裝飾器類
class logit(object):
? ? def __init__(self,logfile="out.log"):
? ? ? ? self.logfile = logfile
? ? def __call__(self,func):
? ??????log_string =?func.__name__ + "was called"
? ? ? ? print(log_string)
? ? ? ? with open(self.logfile,'a') as opened_file:
? ? ? ? ? ? opened_file.write(log_string + "\n")
? ? ? ? #寫完日志后發(fā)送通知
????????self.notify()
? ? def notify(self):
? ? ? ? pass
@logit
def func1():
? ? pass
接著給logit創(chuàng)建子類來實現(xiàn),發(fā)送郵件通知的功能
import smtplib
from email.mime.text import MIMEText
from email.header import Header
class email_logit(logit):
? ? def __init__(self, email = "recv@163.com", *args, **kwargs):
? ? ? ? self.recv_email = email
? ? ? ? super(logit, self).__init__(*args, **kwargs)
? ? def notify(self):
? ??????smpt_host = "smtp.163.com"
? ? ? ? send_email = "sender@163.com"
? ? ? ? pwd = "123456"
? ? ? ? smtp = smtplib.SMTP()
? ? ? ? smtp.connect(smpt_host)
? ? ? ? smtp.login(send_email, pwd)
? ? ? ? message =?MIMEText("logfile is done", 'plain', 'utf-8')
? ? ? ? message["From"] = Header("發(fā)件人", 'uft-8')
? ? ? ? message["To"] = Header("收件人",?'uft-8')
? ? ? ? message["Subject"] = Header("郵件測試",?'uft-8')
? ? ? ? smtp.sendmail(send_email, self.recv_email, message.as_string())
? ? ? ? smtp.quit()
從現(xiàn)在起噪舀, @email_logit將會和@logit產(chǎn)生同樣的效果魁淳, 但是在打?志的基礎上飘诗, 還會多發(fā)送?封郵件給管理員。