装饰器的建议版本
核心思想:
在不改变被装饰对象内部代码和原有调用方式的基础之上添加额外的功能
# 给index函数添加统计执行时间的功能 def index(): time.sleep(3) index() import time def index(): time.sleep(3) print('from index') def home(): time.sleep(2) print('from home') def func(): time.sleep(2) print('from home') def outer(func): # func = index def get_time(): # func:index # 1. 在函数执行之前打一个时间点 start_time = time.time() func() # index() # 2. 在函数执行完毕之后在打一个时间点 end_time = time.time() # 3. 两个时间的差值就是函数的实际执行时间 print("函数执行了:%s秒" % (end_time - start_time)) return get_time # 利用闭包的形式来传参 # res = outer(index) # res:get_time的内存地址 # res() # get_time() home = outer(home) home()
解决参数的问题
def index(name, username): time.sleep(3) print('from index') def home(name): time.sleep(2) print('from home', name) def outer(func): # func = index def get_time(*args, **kwargs): # func:index # 1. 在函数执行之前打一个时间点 start_time = time.time() func(*args, **kwargs) # index() func('tony') # 2. 在函数执行完毕之后在打一个时间点 end_time = time.time() # 3. 两个时间的差值就是函数的实际执行时间 print("函数执行了:%s秒" % (end_time - start_time)) return get_time index = outer(index) index('tony', username='tank')
解决返回值问题
def home(name): time.sleep(2) print('from home', name) def index(): time.sleep(3) print('from index') return 'from index' def outer(func): # func = index def get_time(*args, **kwargs): # func:index # 1. 在函数执行之前打一个时间点 start_time = time.time() res=func(*args, **kwargs) # index() func('tony') # 2. 在函数执行完毕之后在打一个时间点 end_time = time.time() # 3. 两个时间的差值就是函数的实际执行时间 print("函数执行了:%s秒" % (end_time - start_time)) return res return get_time index = outer(index) res=index() print(res)
课堂练习(登录认证功能)
def home(name): print('from home') def func(): print('from func') """ 必须登录之后才能执行index函数 如果不登录不让执行 """ def login_auth(func): # func = index def auth(*args, **kwargs): # 写登录功能 # 1. username = input('username:').strip() password = input('password:').strip() # 2. 验证用户名和密码是否正确 if username == 'kevin' and password == '123': print('登录成功') res=func(*args, **kwargs) return res else: print('用户名或者密码错误') return auth home=login_auth(home) home('kevin')
装饰器模板
def outer(func): def inner(*args, **kwargs): print('这个是函数执行之前可以添加的功能') res = func(*args, **kwargs) print('这个是函数执行之后可以添加的功能') return res return inner def index(): print('from index') index = outer(index) index()
装饰器的语法糖
def outer(func): def inner(*args, **kwargs): print('这个是函数执行之前可以添加的功能') res = func(*args, **kwargs) print('这个是函数执行之后可以添加的功能') return res return inner """装饰器本质就是函数,函数就是功能""" # 语法糖 @outer # index = outer(index) def index(): print('from index') @outer # home=outer(home) -----------> home是outer函数的返回值(内部函数的函数名) def home(): print('from home') home() # inner() # index = outer(index) index() # home = outer(home) # home() """ 语法糖的书写规范: 紧贴着被装饰对象的上方写 语法糖的内部原理: 他会自定把被装饰对象的名字当成参数传给装饰器函数调用 """ @outer # func = outer(func) def func(): print('from func') func() # inner()
双层语法糖
def login_auth(func): # func = index def auth(*args, **kwargs): # 写登录功能 # 1. username = input('username:').strip() password = input('password:').strip() # 2. 验证用户名和密码是否正确 if username == 'kevin' and password == '123': print('登录成功') res = func(*args, **kwargs) return res else: print('用户名或者密码错误') return auth def get_time(func): # func = index def inner(*args, **kwargs): # func:index # 1. 在函数执行之前打一个时间点 start_time = time.time() res = func(*args, **kwargs) # index() func('tony') # 2. 在函数执行完毕之后在打一个时间点 end_time = time.time() # 3. 两个时间的差值就是函数的实际执行时间 print("函数执行了:%s秒" % (end_time - start_time)) return res return inner @login_auth # index=login_auth(get_time内部的inner函数名) @get_time # get_time内部的inner函数名=get_time(index) def index(): time.sleep(2) print('from index') index() # auth()
多语法糖练习题
# 判断七句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')
多认证登录功能
def login_auth(func): # func = index def auth(*args, **kwargs): # 判断用户是否登录了 if is_login.get('is_login'): # 正常执行函数 res = func(*args, **kwargs) return res # 写登录功能 # 1. username = input('username:').strip() password = input('password:').strip() # 2. 验证用户名和密码是否正确 if username == 'kevin' and password == '123': print('登录成功') res = func(*args, **kwargs) is_login['is_login'] = True return res else: print('用户名或者密码错误') return auth @login_auth def index(): print('from index') @login_auth def home(): print('from home') index() home()
装饰器的修复技术(了解)
from functools import wraps def outer(func): # func = index @wraps(func) def get_time(*args, **kwargs): # func:index # 1. 在函数执行之前打一个时间点 start_time = time.time() res = func(*args, **kwargs) # index() func('tony') # 2. 在函数执行完毕之后在打一个时间点 end_time = time.time() # 3. 两个时间的差值就是函数的实际执行时间 print("函数执行了:%s秒" % (end_time - start_time)) return res return get_time
有参装饰器
# 有参装饰器就是带参数的装饰器 # 先前我们学习的装饰器就是无参装饰器:不到参数的装饰器 def outter(type): # type = 1 def login_auth(func): # func = index def auth(*args, **kwargs): # 写登录功能 # 1. username = input('username:').strip() password = input('password:').strip() # 2. 验证用户名和密码是否正确 # with open('') """ 根据不同的参数用户名和密码来自于不同的位置 """ if type == 'file': print('用户名和密码来自于文件') elif type == 'mysql': print('用户名和密码来自于MySQL') elif type == 'oracle': print('用户名和密码来自于Oracle') # if username == 'kevin' and password == '123': # print('登录成功') # res = func(*args, **kwargs) # return res # else: # print('用户名或者密码错误') return auth return login_auth # @login_auth # 如果是index函数认证,用户名和密码来自于文件 login_auth(index, 1) @outter('file') # @login_auth # 如果是index函数认证,用户名和密码来自于文件 login_auth(index, 1) def index(): print('from index') index() # @login_auth # 如果是home函数认证,用户名和密码来MySQL @outter('mysql') # 如果是home函数认证,用户名和密码来MySQL def home(): print('from home') home() @outter('oracle') # 如果是func函数认证,用户名和密码来oracle def func(): print('from func') func()