装饰器
什么是装饰器
装饰器遵循在不改变装饰对象(函数)原有的“调用方式”和“内部代码”的情况下给被装饰对象添加新的功能。装饰器的原则是对扩展开放,对修改封闭
为什么要用装饰器
在项目完成后,需要在原有的基础上有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况这就用到了装饰器
装饰器的实现
简易版本装饰器
import timedef index():time.sleep(3) # 5.停止3秒print("from function index") # 6.输出# 要求:给index函数增加了一个统计执行时间的功能def outer(func):def get_time(): # 2.把index函数名绑定给funcstart_time = time.time() # 3.开始计时func() # 4.调用index函数end_time = time.time() # 计时结束print(end_time - start_time) # index()执行的时间return get_timeindex = outer(index) # 1.通过调用get_time函数把index函数名当做参数传进去index() # 可以看做似调用的index其实调用的是get_time# from function index# 3.0043959617614746print(index) # 全局名称空间中的index指向的是get_time函数体代码# <function outer.<locals>.get_time at 0x7fcf403edf28>
进阶版本装饰器
# 解决不同函数,需要传的参数个数问题def outer(func_name):def get_time(*args, **kwargs):start_time = time.time()func_name(*args, **kwargs)end_time = time.time()print(end_time - start_time)return get_time
完整版本装饰器
# 解决无法返回值问题def outer(func_name):def get_time(*args, **kwargs):start_time = time.time()res = func_name(*args, **kwargs)end_time = time.time()print(end_time - start_time)return resreturn get_time
装饰器模板(重要)
def outer(func_name):def inner(*arg, **wargs):print("修改前的操作")res = func_name(*arg, **kwargs)print("修改后的操作")return resreturn inner
装饰器语法糖
# 仅仅是让代码编写的更加好看、简洁!!!def outer(func_name):def inner(*arg, **kwargs):print("修改前的操作")res = func_name(*arg, **kwargs)print("修改后的操作")return resreturn inner@outer # 等价于 index = outer(index)def index():print("from function index")index()
装饰器“修复技术”
# 做到比真的还要真 但是本质其实没有变from functools import wrapsdef outer(func_name):@wraps(func_name)def inner(*arg, **kwargs):print("修改前的操作")res = func_name(*arg, **kwargs)print("修改后的操作")return resreturn inner@outerdef index():"""这是注释"""print('from function index')help(index) # help可以查看指定函数的注释信息index()# 修改前的操作# from function index# 修改后的操作
多层装饰器
"""语法糖会将紧挨着的被装饰对象的名字当做参数自动传入装饰器函数中"""def outer_1(func_1):print('加载了outer_1')def inner_1(*args, **kwargs):print('执行了inner_1')res1 = func_1(*args, **kwargs)return res1return inner_1def outer_2(func_2):print('加载了outer_2')def inner_2(*args, **kwargs):print('执行了inner_2')res2 = func_2(*args, **kwargs)return res2return inner_2def outer_3(func3):print('加载了outer_3')def inner_3(*args, **kwargs):print('执行了inner_3')res3 = func3(*args, **kwargs)return res3return inner_3@outer_1 # index = outer_1(index)@outer_2 # index = outer_2(index)@outer_3 # index = outer_1(outer_2(outer_3(index)))def index():print('from function index')index()# 加载了outer_3# 加载了outer_2# 加载了outer_1# 执行了inner_1# 执行了inner_2# 执行了inner_3# from function index
有参装饰器
def outer(source_data): # 用来给装饰器传递值def login_auth(func_name): # 不能动,只能接收一个被装饰对象名字def inner(*args, **kwargs): # 不能动,是专门用来给被装饰的对象传参的if source_data == '1':print('操作1')elif source_data == '2':print('操作2')elif source_data == '3':print('操作3')else:print('其他操作')res = func_name(*args, **kwargs)return resreturn innerreturn login_authnum = input("输入你要操作的方式:")@outer(num)def index():print('from function index')index()
类作为装饰器
class Decorator(object):def __init__(self, f):self.f = fdef __call__(self):print("进入", self.f.__name__)self.f()print("退出", self.f.__name__)@Decoratordef func():print("执行 func1()")func()# 进入 func# 执行 func1()# 退出 func
对象作为装饰器
class Decorator:def __init__(self, arg1, arg2):print('执行类Decorator的__init__()方法')self.arg1 = arg1self.arg2 = arg2def __call__(self, f):print('执行类Decorator的__call__()方法')def wrap(*args):print('执行wrap()')print('装饰器参数:', self.arg1, self.arg2)print('执行' + f.__name__ + '()')f(*args)print(f.__name__ + '()执行完毕')return wrap@Decorator('Hello', 'World')def example(a1, a2, a3):print('传入example()的参数:', a1, a2, a3)print('装饰完毕')print('准备调用example()')example('Wish', 'Happy', 'EveryDay')print('测试代码执行完毕')
