装饰器概念
装饰器就是修改增加其他函数功能的特殊函数,有助于让代码更简短。
装饰器都是高阶函数,但装饰器是对传入函数功能的装饰和增强
无参装饰器
- 是一个函数
- 函数作为它
- 的形参
- 返回值也是一个函数
- 使用@functionname方式,@下的函数名称会作为装饰器的参数传给装饰器。
示例
对加法函数进行功能增强
def logger(fn):def wapper(*args, **kwargs):print('begin')x = fn(*args, **kwargs)print('end')return xreturn wapper@logger # 等价于add = logger(add)def add(x, y):return x + yprint(add(40, 50))print(add.__name__)# outputbeginend90wapper
这里会发现一个问题,add.name应该输出的是add,这里被装饰器wapper替代了,这是因为装饰器会重写我们函数的名字和注释文档,Python提供了一个函数来解决这个问题,functools.wraps,修改如下
from functools import wrapsdef logger(fn):@wraps(fn)def wapper(*args, **kwargs):print('begin')x = fn(*args, **kwargs)print('end')return xreturn wapper@loggerdef add(x, y):return x + yprint(add(40, 50))print(add.__name__)# outputbeginend90add
带参装饰器
- 带参装饰器也是一个函数
- 函数作为它的形参
- 返回值是一个不带参的装饰器函数
- 使用@functionname(参数列表)方式调用
- 可以看做在装饰器外层又增加了一层函数
示例
from functools import wrapsdef logger(logfile='test.log'): # 带参装饰器def _logging(fn): # 将被装饰的函数作为参数传入@wraps(fn) # 等价于wraps= wraps(fn)(wapper)def wapper(*args, **kwargs):log_string = fn.__name__ + ' was called'print(log_string)with open(logfile, 'a') as f:f.write(log_string + '\n')return fn(*args, **kwargs) # 装饰后将原函数返回return wapperreturn _logging@logger(logfile='out.log')def add(x, y):return x+yprint(add(5,6))# 这里会出现一个叫out.log的文件,里面的内容就是装饰器装饰过的字符串
类装饰器
除了上面的装饰器函数,类也能构建装饰器。
下面使用类来重新构建logger
from functools import wrapsclass logger():def __init__(self, logfile='test.log'):self.logfile = logfiledef __call__(self, fn): # 类装饰器主要依赖call方法来实现@wraps(fn)def wapper(*args, **kwargs):log_string = fn.__name__ + ' was called'print(log_string)with open(self.logfile, 'a') as f:f.write(log_string + ' 类装饰器')return fn(*args, **kwargs)return wapper@logger(logfile='out.log')def add(x, y):return x+yprint(add(5,11))
- 相比函数装饰器,类装饰器灵活度更好,使用类装饰器主要依靠类的call方法,使用方法同样使用@加装饰器名称方法
