装饰器
装饰器?
- 什么是装饰器?
装饰器本质上是一个 Python 函数,它可以让其函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。装饰器常用场景有:插入日志、授权、计算脚本运行时间、事务处理、缓存等。
- 加了装饰器后函数是怎么运行的?
def new_deco(func):
def wrapped_func(*args,**kwargs):
print("before executing func")
func(*args,**kwargs)
print("after executing func")
return wrapped
@new_deco
def test_func():
print("start to executing func")
test_func()
print("the test_func name is:{}".format(test_func.__name__))
# Outputs:
# "before executing func"
# "start to executing func"
# "after executing func"
# "the test_func name is:wrapped_func"
test_func 函数的函数名被 wrapped_func。它重写了我们函数的名字和注释文档(docstring)
from functools import wraps
def new_deco(func):
@wraps(func)
def wrapped(*args,**kwargs):
print("before executing func")
func(*args,**kwargs)
print("after executing func")
return wrapped
@new_deco
def test_func():
print("start to executing func")
test_func()
print("the test_func name is:{}".format(test_func.__name__))
# Outputs:
# "before executing func"
# "start to executing func"
# "after executing func"
# "the test_func name is:test_func"
@wraps 接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
- 不带参数装饰器的示例
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):
"""Do some math."""
return x + x
# Output: addition_func was called
- 带参数的装饰器
- 理解:在函数中嵌入装饰器
- 示例:
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 func(*args, **kwargs)
return wrapped_function
return logging_decorator
@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 的文件出现了,里面的内容就是上面的字符串
- 类装饰器
- 概念:类装饰器具有灵活度大、高内聚、封装性等优点。可依靠内部的 call 方法
- 示例:
from functools import wraps
class logit(object):
def __init__(self, logfile='out.log'):
self.logfile = logfile
def __call__(self, func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile并写入
with open(self.logfile, 'a') as opened_file:
# 现在将日志打到指定的文件
opened_file.write(log_string + '\n')
# 现在,发送一个通知
self.notify()
return func(*args, **kwargs)
return wrapped_function
def notify(self):
# logit只打日志,不做别的
pass
@logit()
def myfunc1():
print("test")
myfunc1()
# Output:myfunc1 was called
# test
- 装饰器的执行顺序
@a
@b
@c
def f ():
a(b(c(f)))
参考资料:
https://eastlakeside.gitbooks.io/interpy-zh/content/decorators/