函数的装饰器语法糖修复技术
目录
- 一:装饰器简易版本
- 二:解决参数问题
- 三:解决返回值问题
- 四:认证装饰器
- 五:装饰器固定模板
- 六:装饰器语法糖
- 七:双层语法糖
- 八:三层语法糖
- 九:装饰器修复技术
- 十:有参装饰器
一:装饰器简易版本
装饰器 :
在不改变被装饰对象"内部代码"以及"调用方式"的基础上添加新的功能
原则
开放封闭原则
对扩展开放
对修改封闭
给函数添加统计执行时间的功能
def outer(func): func指向的是函数名index
func = index
def get_time():
start_time = time.time()
func()
end_time = time.time()
print('函数运行时间:%s' % (end_time - start_time))
return get_time # 将get_time函数名返回出去
index = outer(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('jason')
index = outer(index)
index()
三:解决返回值问题
import time
定义一个函数
def index():
计时器3秒
time.sleep(3)
输出
print('亚洲最大赌场开业了 女优在线发牌')
返回值
return 'from index'
定义函数
def login(name):
计时器
time.sleep(1)
输出
print('著名:%s 在线发牌' % name)
返回值
return 'from login'
第二种函数传参的方式
定义函数 成为闭包函数
def outer(func): # func指向的是函数名index
写死
func = index
定义函数
一个用于接收多余的位置参数 一个用于接收多余的关键字参数
def get_time(*args, **kwargs):
1970年距离在的秒数
start_time = time.time()
调用函数
一个用于接收多余的位置参数 一个用于接收多余的关键字参数
res = func(*args, **kwargs) # 接收被装饰函数的返回值
1970年距离现在的秒数
end_time = time.time()
1970年距离现在的秒数相减,中间停顿3秒,得出现在的结果
print('函数运行时间:%s' % (end_time - start_time))
return res # 执行完get_time之后返回被装饰函数执行之后的返回值
返回值
return get_time # 将get_time函数名返回出去
调用函数 赋值
index = outer(index)
res = index()
print(res)
login = outer(login)
res1 = login('jason')
print(res1)
四:认证装饰器
定义一个框架
import time
定义一个函数
def index():
计时器1秒
time.sleep(1)
输出
print('百万大奖等您来拿 赶快加入我们吧!!')
def home():
time.sleep(1)
print('学学学 一天到晚就是学')
def register():
time.sleep(1)
print('注册功能')
给index函数添加认证功能
'''
在调用index之前需要用户输入用户名和密码
正确才可以调用
错误直接拒绝
只要登录一次成功了 就不需要验证了
'''
全局定义一个用于记录用户是否登录的数据
is_login = {'is_login':False}
定义函数 装饰器
def login_auth(func):
定义函数
def auth(*args, **kwargs):
先判断用户是否已登录
if is_login.get('is_login'):
正常执行函数index
res = func(*args, **kwargs)
return res
1.先获取用户的用户名和密码
username = input('请输入您的用户名:').strip()
password = input('请输入您的密码:').strip()
2.校验用户名和密码是否正确
if username =='jason' and password == '123':
# 3.正常执行函数index
res = func(*args, **kwargs)
# 将记录用户登录状态的数据修改
is_login['is_login'] = True
return res
用户输入错误
else:
print('用户名或密码错误')
返回值
return auth
index = login_auth(index)
index()
home = login_auth(home)
home()
register = login_auth(register)
register()
五:装饰器固定模板
def index(*args, **kwargs):
print('func index')
定义一个函数
def outer(func):
定义一个内部函数
def inner(*args, **kwargs):
print('大驾光临')
执行装饰器函数
res = func(*args, **kwargs)
print('大驾光临本店')
return inner
index = outer(index)
index()
六:装饰器语法糖
def outer(func): # func = index
# 定义函数 一个用于接收多余的位置参数 一个用于接收多余的关键字参数
def inner(*args, **kwargs):
# 输出
print('执行函数之前可以添加的额外功能')
# 执行被装饰的函数
func(*args, **kwargs)
print('执行函数之后可以添加的额外功能')
# 将被装饰函数执行之后的返回值返回
# 返回值
return inner
@outer # index = outer(index)
def index(*args, **kwargs):
print('from index')
index()
'''
装饰器语法糖是写规范
语法糖必须紧贴在被装饰对象的上方
装饰器语法糖内部原理
会自动将下面紧贴着的被装饰对象名字自动传给装饰器函数
'''
七:双层语法糖
统计函数运行时间
import time
def get_time(func):
定义函数 一个用于接收多余的位置参数 一个用于接收多余的关键字参数
def inner1(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs) # 执行被装饰的函数
end_time = time.time()
print('函数执行时间:%s' % (end_time-start_time))
return res # 将被装饰函数执行之后的返回值返回
返回值
return inner1
校验用户登录装饰器
def login_auth(func):
def inner2(*args, **kwargs):
1.先获取用户名和密码
username = input('请输入您的用户名:')
password = input('请输入您的密码:')
2.校验用户名和密码是否正确
if username == 'jason' and password == '123':
res = func(*args, **kwargs) # 执行被装饰的函数
return res # 将被装饰函数执行之后的返回值返回
else:
print('用户名或密码错误 无权限执行')
return inner2
装饰顺序由下往上 遇到最后一个才会使用与函数名相同的变量名命名
@login_auth # index = login_auth(inner1)
@get_time # get_time(index)
def index():
time.sleep(1)
print('from index')
get_time(index)
index = login_auth(inner)
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 # index = outter1 (wrapper2) index = wrapper1
@outter2 # outter2(wrapper3)
@outter3 # outter3(index)
def index():
print('from index')
index() # wrapper1()
'''
装饰器语法糖书写规范
语法糖必须紧贴在被装饰对象的上方
装饰器语法糖内部原理
会自动将下面紧贴着的被装饰对象名字当做参数传给装饰器函数调用'''
九:装饰器修复技术
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)
help(index)
def home():
"""这是一个home函数"""
print('from home')
help(index)
help(home)
print(index)
help(len)
十:有参装饰器
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()