装饰器
装饰器介绍
1、装饰器是由所学的名称空间、函数对象、闭包函数组合而来的
器:指的是工具
装饰:给被装饰对象添加额外的功能
2、装饰器的原则
开放封闭原则
开放:对扩展开放
封闭:对修改封闭
3、装饰器的核心思想
在不改变被装饰对象内部代码和原有调用方式的基础上添加额外功能
def index(): print('from index') index()
装饰器简易版本
import time def index(): time.sleep(3) print('原地休息') def outer(func): # func指向的是函数名index # func = index def get_time(): start_time = time.time() func() end_time = time.time() print('原地休息的时间%s'%(start_time-end_time)) return get_time # 将get_time函数名返回出去 index = (outer(index)) # # 左侧的变量名index指代是函数名get_time index()
运行步骤
装饰器进阶
解决参数问题
代码
import time def index(): time.sleep(3) print('今天也是美好的一天') def login(name): time.sleep(1) print('%s来了' % name) def outer(func): # func指向的是函数名login # func = login def get_time(*args,**kwargs): start_time = time.time() func(*args,**kwargs) end_time = time.time() print('函数运行时间:%s' % (end_time - start_time)) return get_time # 将get_time函数名返回出去 login = outer(login) login('tony') index = outer(index) index()
图示
解决返回值
代码
import time def index(): time.sleep(3) print('今天也是美好的一天') return 'from index' def outer(func): # func指向的是函数名login # func = login def get_time(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) end_time = time.time() print('函数运行时间:%s' % (end_time - start_time)) return res return get_time # 将get_time函数名返回出去 index = outer(index) res = index() print(res)
图示
装饰器固定模板
def outer(func): def inner(*args, **kwargs): print('执行函数之前可以添加的的额外功能') res = func(*args, **kwargs) # 执行被装饰的函数 print('执行函数之后可以添加的额外功能') return res # 将被装饰函数执行之后的返回值返回 return inner
装饰器之语法糖
1、装饰器语法糖书写规范:语法糖必须紧贴在被装饰对象的上方
2、装饰器语法糖内部原理:会自动将下面紧贴着的被装饰对象名字当作参数传给装饰器函数调用
3、格式
def outer(func): def inner(*args, **kwargs): print('执行函数之前可以添加的额外功能') res = func(*args, **kwargs) # 执行被装饰的函数 print('执行函数之后可以添加的额外功能') return res # 将被装饰函数执行之后的返回值返回 return inner @outer # index = outer(index) def index(*args, **kwargs): print('from index') index()
4、双层语法糖
# 统计函数运行时间 import time def get_time(func): def inner(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) # 执行被装饰的函数 end_time = time.time() print('函数执行时间:%s'%(end_time-start_time)) return res # 将被装饰函数执行之后的返回值返回 return inner # 校验用户登录装饰 def login_auth(func): def inner(*args, **kwargs): # 1.先获取用户的用户名和密码 username = input('username>>>:').strip() password = input('password>>>:').strip() # 2.校验用户名和密码是否正确 if username == 'tony' and password == '123': res = func(*args, **kwargs) # 执行被装饰的函数 return res # 将被装饰函数执行之后的返回值返回 print('用户名或密码错误 无权限执行') return inner @login_auth @get_time def index(): time.sleep(1) print('from index') index()
练习题
判断七句print执行顺序
def outter1(func1): print('加载了outter1') def wrapper1(*args, **kwargs): print('执行了wrapper1') res1 = func1(*args, **kwargs) return res1 return wrapper1 def outter2(func2): print('加载了outter2') def wrapper2(*args, **kwargs): print('执行了wrapper2') res2 = func2(*args, **kwargs) return res2 return wrapper2 def outter3(func3): print('加载了outter3') def wrapper3(*args, **kwargs): print('执行了wrapper3') res3 = func3(*args, **kwargs) return res3 return wrapper3 @outter1 @outter2 @outter3 def index(): print('from index') ''' 结果: 加载了outter3 加载了outter2 加载了outter1 '''
图示
装饰器修复技术
代码
from functools import wraps def outer(func): @wraps(func) # 修复技术就是为了让被装饰对象更加不容易被察觉装饰了 def inner(*args, **kwargs): print('执行函数之前可以添加的额外功能') res = func(*args, **kwargs) # 执行被装饰的函数 print('执行函数之后可以添加的额外功能') return res # 将被装饰函数执行之后的返回值返回 return inner @outer # index = outer(index) def index(): print('from index') print(index) # <function index at 0x000001C26C76F158>
图示
有参函数
def outer(source_data): # source_data = 'file' def login_auth(func): def auth(*args,**kwargs): # 2.校验用户名和密码是否正确 # 数据的校验方式可以切换多种 if source_data == 'file': # 从文件中获取用户数据并比对 print('file文件获取') elif source_data == 'MySQL': # 从MySQL数据库中获取数据比对 print('MySQL数据库获取') elif source_data == 'postgreSQL': # 从postgreSQL数据库中获取数据对比 print('postgreSQL数据库获取') else: print('用户名或密码错误 无法执行函数') return auth return login_auth @outer('file') def index(): print('from index') @outer('MySQL') def home(): print('from home') index() home()