python-装饰器
装饰器
简述
如果我们想给一个类扩充功能,我们可以通过继承和组合,但是如果我们如果想给一个方法添加额外的功能呢?
装饰器可以满足这个需求。
装饰器是一个可调用的对象,其参数是一个函数,这个函数通常称为被装饰的函数。
装饰器可能会处理被装饰的函数,然后返回一个函数或一个可调用对象。
来个栗子,有一个名为decorate的装饰器
def decorate(func): def inner(): print("inner") return inner @decorate def target(): print("target") target() #inner
上述的代码等价于下述的代码
def decorate(func): def inner(): print("inner") return inner def target(): print("target") target = decorate(target) target() #inner
装饰器特性
(1)能把被装饰的函数替换了其他的函数
这个特性从上面的栗子就可以看出
(2)装饰器在加载模块时立即执行
被装饰的函数只有在调用时才执行
def decorate(func): print('decorate functon:', func.__name__) def inner(): print('inner') return inner @decorate def func1(): print('func1') if __name__ == '__main__': func1()
导入时,如果我在另一个模块导入上述代码所在的模块,结果如下:
import decorate #decorate functon: func1
运行时,如果我直接运行这个模块,结果如下:
#decorate functon: func1 #inner
一般而言,装饰器通常在一个模块中定义,然后应用到其他模块中的函数上,大多数装饰器会在内部定义一个函数然后将其返回。
装饰器的典型行为
把被装饰的函数替换成新的函数,两者接受相同的参数,返回被装饰的函数本该返回的值,
同时,还会做些额外操作。
实际应用
计时统计、记录日志,缓存运算结果等
案例1
编写一个记录函数运行时间的装饰器
import time def log_time(func): def run_time(*args, **kwargs): begin_time = time.time() res = func(*args, **kwargs) print('spent {}s'.format(time.time() - begin_time))
return res return run_time @log_time def sleep_func(): time.sleep(1) sleep_func()
案例2
使用类编写一个装饰器
import time class LogTime: def __call__(self, func): def run_time(*args, **kwargs): begin_time = time.time() res = func(*args, **kwargs) print('spent {}s'.format(time.time() - begin_time)) return res return run_time @LogTime() def sleep_func(): time.sleep(1) sleep_func()
案例3
给装饰器传递参数
class LogTime: def __init__(self, use_int): self.use_int = use_int def __call__(self, func): def run_time(*args, **kwargs): begin_time = time.time() res = func(*args, **kwargs) if self.use_int: print('spent {}s'.format(int(time.time() - begin_time))) else: print('spent {}s'.format(time.time() - begin_time)) return res return run_time @LogTime(use_int=True) def sleep_func(): time.sleep(1) sleep_func
参考资料:《流畅的python》