装饰器让你在⼀个函数的前后去执⾏代码。
封装⼀个函数, 并且⽤这样或者那样的⽅式来修改它的⾏为,这就是装饰器所做的事情。
列如:
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再执行看看
注意: @wraps接受⼀个函数来进⾏装饰, 并加⼊了复制函数名称、 注释⽂档、 参数列表等等的功能。 这可以让我们在装饰器⾥⾯访问在装饰之前的函数的属性。
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、在函数中嵌入装饰器,构建带参数的装饰器
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
执行func1,会生成out.log的日志文件
@logit(logfile="func2.log")
def func2():
pass
执行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")
#写完日志后发送通知
self.notify()
def notify(self):
pass
@logit
def func1():
pass
接着给logit创建子类来实现,发送邮件通知的功能
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("发件人", 'uft-8')
message["To"] = Header("收件人", 'uft-8')
message["Subject"] = Header("邮件测试", 'uft-8')
smtp.sendmail(send_email, self.recv_email, message.as_string())
smtp.quit()
从现在起, @email_logit将会和@logit产生同样的效果, 但是在打⽇志的基础上, 还会多发送⼀封邮件给管理员。
网友评论