python 装饰器
装饰器的本质是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。
装饰器返回值是一个函数;接收参数也是一个函数(参数是我们业务要执行的函数)。
一个简单示例
python
# 定义一个简单的装饰器
def a_new_decorator(a_func):
def wrapTheFunction():
print("before executing a_func()"
a_func()
print("after executing a_func()"
return wrapTheFunction
def a_function():
print('main func')
# 装饰器执行的过程
a_function = a_new_decorator(a_function)
a_function()
过程:装饰器把要执行的函数作为参数传给自己,在创建一个同名函数对象代替要执行的函数
使用@
python
@a_new_decorator
def a_function():
print('main func')
a_function()
# 执行效果同上
functools.wraps
functools.wraps保留原函数的名字和注释文档(docstring)
python
from functools import wraps
# 定义一个装饰器
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print("before executing a_func()"
a_func()
print("after executing a_func()"
return wrapTheFunction
函数参数
参数可以通*args、**kwargs
python
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return "Function will not run"
return f(*args, **kwargs)
return decorated
@decorator_name
def func(msg:str):
print(msg)
return("Function is running")
can_run = True
print(func("hahah"))
# Output: hahah
# Output: Function is running
带参数的装饰器
外层再套一个函数
python
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile,并写⼊内容
with open(logfile, 'a') as opened_file:
# 现在将⽇志打到指定的logfile
opened_file.write(log_string + '\n')
return wrapped_function
return logging_decorator
python
@logit()
def myfunc1():
pass
myfunc1()
# Output: myfunc1 was called
# 现在⼀个叫做 out.log 的⽂件出现了,⾥⾯的内容就是上⾯的字符串
@logit(logfile='func2.log')
def myfunc2():
pass
myfunc2()
# Output: myfunc2 was called
# 现在⼀个叫做 func2.log 的⽂件出现了,⾥⾯的内容就是上⾯的字符串
装饰类
类也可以用来构建装饰器
python
class logit(object):
def __init__(self,logfile='out.log'):
self.logfile = logfile
# __call__ :可以使用类名调用__call__函数的实现
def __call__(self,func):
log_string = func.__name__+" was called"
print(log_string)
with open(self.logfile,'a') as open_file:
open_file.write(log_string+"\n")
self.notify()
def notify(self):
# 打印日志
pass
python
@logit()
def func1():
pass
可以继承logit,扩展功能
python
# 来添加email的功能,保留原来的记录日志的功能
class email_logit(logit):
def __init__(self, email='admin@myproject.com', *args, **kwargs)
self.email = email
super(logit, self).__init__(*args, **kwargs)
def notify(self):
# 打印日志
# send emil
pass