所谓装饰器decorator仅仅是一种语法糖, 可作用的对象可以是函数也可以是类, 装饰器本身是一个函数, 其主要工作方式就是将被装饰的类或者函数当作参数传递给装饰器函数。本质上,装饰器就是一个返回函数的高阶函数
假设有这么一个应用场景,一个公司的监控监控系统有很多函数用来监控不同的数据,突然有一天老大要把这么多函数,需要一个日志功能,也就是在执行函数前和执行函数后再控制台和文件中输出日志。
如果老大把这个任务交个你,你会怎么做?把每个函数都修改一遍吗?如果老大觉得日志功能太影响性能,又要去掉,怎么办?一个又一个的改回来??如果函数少需要修改的地方少还可以,如果需要修改的地方很多的话,这样显然是不明智的。用装饰器就可以很好的解决这个问题。我们先来看一下装饰器如何定义。
定义装饰器
def log(func):
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
return func(*args, **kwargs)
return wrapper
说明:看上去和定义一个函数没多大区别,只不过在函数里有嵌套了一层函数而已。1)log为装饰器名称,可以随意定义,就像普通函数。2)装饰器的参数
func
为一个函数,表示要装饰的函数。(Python解释会自动将这个被装饰的函数作为参数传递给func
)3)装饰器里面的函数名可以随意,参数的话可以根据被装饰的函数的情况而定,参数的作用只是为了把参数有重新传回被装饰的函数。通常使用*args
和**kwargs
为了可以匹配各种函数的参数个数等
装饰器的调用
调用装饰器来装饰函数,我们只需要使用Python的语法糖,在被装饰函数上方使用@装饰器名
的方式调用,比如我们要调用上面的log
装饰器
@log
def Foo():
print('Foo')
Foo()
执行结果
call Foo():
Foo
装饰器原理
其实装饰器的调用@装饰器名是一个语法糖,Python解释器在解释到这里的时候为我们做了如下操作
Foo = log(Foo)
说明:
1)调用装饰器函数将被装饰的函数作为参数传递过去。
2)这样就相当于重构了这个函数,也就是包裹了一层内容。
3)装饰器本身一个可以接收参数,但是,由于使用场合比较少,甚少会用到,这里就不讲解了,其实原理就是在定义装饰器的时候在外面再裹上一层函数