装饰器本质上就是一个Python函数,它可以让其它函数在不需要做任何代码变动的前提下增加额外功能。装饰器的返回值也是一个函数对象。
装饰器经常用于有切面需求的场景,比如:插入日志、性能检测、事务处理、缓存、权限校验等场景。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
下面是一个简单的装饰器。@use_logging 的作用就是将它下面的函数输入到装饰函数use_logging里面。装饰函数use_logging调用并返回了内置的warpper函数,相当于bar = use_logging(bar) = wrapper(*args,**kwargs)。证明就是当我们输出bar.__name__时,输出的却是wrapper,而且bar.__doc__的内容也丢失了。这时的bar()函数已经被wrapper函数替换了,bar()的函数体被作为wrapper的返回值。
import logging
def use_logging(func):
def wrapper(*args, **kwargs):
logging.warn('%s is running!'%func.__name__)
return func(*args, **kwargs)
return wrapper
@use_logging
def bar(name):
"""THIS IS bar's doc!"""
print('i am %s!'%name)
bar('wtx')
print(bar.__name__)
print(bar.__doc__)
输出:
如何保留原函数的__name__属性和__doc__属性这样的元信息呢?
使用functools.wraps
wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器函数中
import logging
from functools import wraps
def use_logging(func):
@wraps(func)
def warpper