在Python中函数也是一个对象,我们可以获得函数对象,然后执行函数
def func(): print('I am very good') a = func a
如果我们要是想增强这个函数呢?比如给它增加功能,在执行前输出一段log日志,表明函数名,但是呢又不想修改func函数的定义,这种在代码运行期间动态增加功能的方式,称之为"装饰器"。我们一步步来解析下它的作用。
按照上面的需求,输出log,可以这样做:
def func(): print('%s is running' % func.__name__) print('I am very good') func()
但是这样做的话我们就修改了func函数的内部结构,所以不能这样,我们优化下:
def func(): print('I am very good') def use_logging(func): print('%s is running' % func.__name__) return func a = use_logging(func) a()
这样是可以解决问题的,但是如果func函数带参数的话怎么办呢?直接use_logging(func(a,b))? 肯定是不对的,这样的话传入的就是一个func函数执行完的结果,那就没办法在它执行前去增加操作了。所以还是要再包装优化下:
def use_logging(func): def wrapper(*args, **kwargs): print('%s is running' % func.__name__) return func(*args, **kwargs) return wrapper a = use_logging(func) a(1, 2)
通过这样包装,得到一个func函数对象,它包含了func函数要做的事情,我们没有破坏它内部的结构。我们use_logging得到的是个wrapper函数对象,而可以通过给这个对象增加参数,从而func函数也可以有参数了,并且可以在func函数执行前增加我们需要的操作。
在Python中装饰器有这样的语法规则,我们不需要写a = use_logging(func) a(),我们只需要在func函数上面加个@use_logging,就可以完成这项工作。
def use_logging(func): def wrapper(*args, **kwargs): print('%s is running' % func.__name__) return func(*args, **kwargs) return wrapper @use_logging def func(a, b): print(a+b) print('I am very good') func(1, 2)
然后我们正常使用func函数就可以了。在我的理解中装饰器就是对函数的一层层包装,注意是包装不是封装,封装的话是为了将冗余重复的代码消除而将这部分代码进行封装使用,包装的话是对一个函数方法内部不做更改而给它增加新的功能,对这个函数进行装饰。