装饰器
什么是装饰器
装饰器遵循在不改变装饰对象(函数)原有的“调用方式”和“内部代码”的情况下给被装饰对象添加新的功能。装饰器的原则是对扩展开放,对修改封闭
为什么要用装饰器
在项目完成后,需要在原有的基础上有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况这就用到了装饰器
装饰器的实现
简易版本装饰器
import time
def index():
time.sleep(3) # 5.停止3秒
print("from function index") # 6.输出
# 要求:给index函数增加了一个统计执行时间的功能
def outer(func):
def get_time(): # 2.把index函数名绑定给func
start_time = time.time() # 3.开始计时
func() # 4.调用index函数
end_time = time.time() # 计时结束
print(end_time - start_time) # index()执行的时间
return get_time
index = outer(index) # 1.通过调用get_time函数把index函数名当做参数传进去
index() # 可以看做似调用的index其实调用的是get_time
# from function index
# 3.0043959617614746
print(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 res
return get_time
装饰器模板(重要)
def outer(func_name):
def inner(*arg, **wargs):
print("修改前的操作")
res = func_name(*arg, **kwargs)
print("修改后的操作")
return res
return inner
装饰器语法糖
# 仅仅是让代码编写的更加好看、简洁!!!
def outer(func_name):
def inner(*arg, **kwargs):
print("修改前的操作")
res = func_name(*arg, **kwargs)
print("修改后的操作")
return res
return inner
@outer # 等价于 index = outer(index)
def index():
print("from function index")
index()
装饰器“修复技术”
# 做到比真的还要真 但是本质其实没有变
from functools import wraps
def outer(func_name):
@wraps(func_name)
def inner(*arg, **kwargs):
print("修改前的操作")
res = func_name(*arg, **kwargs)
print("修改后的操作")
return res
return inner
@outer
def 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 res1
return inner_1
def outer_2(func_2):
print('加载了outer_2')
def inner_2(*args, **kwargs):
print('执行了inner_2')
res2 = func_2(*args, **kwargs)
return res2
return inner_2
def outer_3(func3):
print('加载了outer_3')
def inner_3(*args, **kwargs):
print('执行了inner_3')
res3 = func3(*args, **kwargs)
return res3
return 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 res
return inner
return login_auth
num = input("输入你要操作的方式:")
@outer(num)
def index():
print('from function index')
index()
类作为装饰器
class Decorator(object):
def __init__(self, f):
self.f = f
def __call__(self):
print("进入", self.f.__name__)
self.f()
print("退出", self.f.__name__)
@Decorator
def func():
print("执行 func1()")
func()
# 进入 func
# 执行 func1()
# 退出 func
对象作为装饰器
class Decorator:
def __init__(self, arg1, arg2):
print('执行类Decorator的__init__()方法')
self.arg1 = arg1
self.arg2 = arg2
def __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('测试代码执行完毕')