装饰器
![image]()
1.初级装饰器
# 定义一个函数index
import time
def index():
time.sleep(1)
print('这是被装饰的对象')
def home():
print('这是一个别装饰的函数')
# 写一个装饰器可以计算函数index运行时间
# 定义一个函数可以调用时实现该功能
def outer(func):
# func = index
def inner():
# 获取函数运行前的时间
start_time = time.time()
# 调用函数
func()
# 获取函数运行结束后的时间
end_time = time.time()
# 打印函数运行的时间
print(f'这是函数{func}的运行时间%s' %(end_time -start_time))
return inner
index = outer(index)
index()
home = outer(home)
home()
'''该装饰器只能简单的实现index函数是无参函数的情况,
且如果该装饰器被多个函数调用时,只能通过在装饰器内部修改参数来实现
不能通过直接调用装饰器时传参来满足不同函数的需求'''
![image]()
2.进阶装饰器
# 当被装饰对象里有参数,且有返回值的时候怎么解决
import time
def index(name):
time.sleep(1)
print('这是一个被装饰的对象%s'%name)
return 'from index'
def home(age):
time.sleep(1)
print('这是一个被装饰的函数%s'%age)
# 统计函数运行时间装饰器
def outer(func):
# func = index
def inner(*args,**kwargs):
# 获取被装饰对象函数运行之前的时间
start_time = time.time()
# 执行被装饰对象函数
res =func(*args,**kwargs)
# 获取被装饰对象函数运行之后的时间
end_time = time.time()
print(f'{end_time - start_time}')
return res
return inner
# index = outer(index)
# res = index('jason')
# print(res)
home = outer(home)
home(18)
![image]()
3.认证程序装饰器
def index(name):
print(f'性感荷官{name}在线发牌')
return '欢迎下次再来!'
def home(name):
print(f'大唐洗浴中心欢迎你,由{name}为您服务')
return '欢迎下次再来'
# 定义一个字典,用来判断用户的登录状态
is_login = {'is_login':False}
def outer(func):
def inner(*args,**kwargs):
# 判断用户的登录状态
if is_login.get('is_login'):
res = func(*args,**kwargs)
return res
# 获取用户的输入
user_name = input('输入你的登录名:').strip()
password = input('输入你的密码:').strip()
# 根据用户的输入进行比对
if user_name == 'jason' and password == '123':
# 如果成功了则调用函数并获取函数的返回值
res = func(*args,**kwargs)
# 用户登录成功,则修改登录的状态,不要再频繁登录
is_login['is_login'] = True
return res
print('登录名或者密码输入错误,请重新输入')
return '下次再来'
return inner
index = outer(index)
res = index('jason')
print(res)
home = outer(home)
res1 = home('jason')
print(res1)
![image]()
4.装饰器修复技术
# 何为装饰器修复技术
当我们使用装饰器装饰某对象时,虽然调用时,形式上看是和被装饰对象的函数名一样,
实际上,只是用一个和被装饰对象函数名相同的变量名指向,可以在不改变原来函数的内部代码和调用方式的
情况下执行原函数,而在调用时执行的函数本身并不是原函数,所以可以用装饰器修复技术,使得我们的装饰器更加的完美
from functools import wraps
import time
# 统计函数运行时间装饰器
def get_time(func):
# func = index
@wraps(func) # 修复技术就是为了让被装饰对象更加不容易被察觉装饰了
def inner1(*args,**kwargs):
# 获取被装饰对象函数运行之前的时间
start_time = time.time()
# 执行被装饰对象函数
res =func(*args,**kwargs)
# 获取被装饰对象函数运行之后的时间
end_time = time.time()
print(f'{end_time - start_time}')
return res
return inner1
is_login = {'is_login':False}
def login(func):
@wraps(func) # 修复技术就是为了让被装饰对象更加不容易被察觉装饰了
def inner2(*args,**kwargs):
# 判断用户的登录状态
if is_login.get('is_login'):
res = func(*args,**kwargs)
return res
# 获取用户的输入
user_name = input('输入你的登录名:').strip()
password = input('输入你的密码:').strip()
# 根据用户的输入进行比对
if user_name == 'jason' and password == '123':
# 如果成功了则调用函数并获取函数的返回值
res = func(*args,**kwargs)
# 用户登录成功,则修改登录的状态,不要再频繁登录
is_login['is_login'] = True
return res
print('登录名或者密码输入错误,请重新输入')
return '下次再来'
return inner2
@login # login(get_time(index)) = inner2 # index = inner2 # index() = inner2()
@get_time # get_time(index) = inner1
def index(name):
print(f'性感荷官{name}在线发牌')
return '欢迎下次再来!'
res = index('jason')
print(res)
print(index) # <function index at 0x000001A2CA1F80D8>
5.装饰器固定模板
from functools import wraps
def outer(func):
@wraps(func) # 装饰器修复技术是为了更不容易被察觉到被装饰对象被装饰了
def inner(*args, **kwargs):
print('这是被装饰对象函数运行前可以添加的额外功能')
# 执行被装饰对象函数
res = func(*args, **kwargs)
print('这是被装饰对象函数运行后可以添加的额外功能')
# 返回被装饰对象执行后的返回值
return res
return inner
'''调用时:
被装饰对象函数名绑定的变量名 = 装饰器函数名(被装饰对象函数名)
res = 被装饰对象函数名绑定的变量名()# 获取被装饰对象的返回值
print(res)
'''
![image]()
6.装饰器语法糖
# 装饰器语法糖是为了在调用装饰器时可以简化代码
# 语法结构:@+装饰器函数名
# 定义一个字典,用来判断用户的登录状态
is_login = {'is_login':False}
def outer(func):
def inner(*args,**kwargs):
# 判断用户的登录状态
if is_login.get('is_login'):
res = func(*args,**kwargs)
return res
# 获取用户的输入
user_name = input('输入你的登录名:').strip()
password = input('输入你的密码:').strip()
# 根据用户的输入进行比对
if user_name == 'jason' and password == '123':
# 如果成功了则调用函数并获取函数的返回值
res = func(*args,**kwargs)
# 用户登录成功,则修改登录的状态,不要再频繁登录
is_login['is_login'] = True
return res
print('登录名或者密码输入错误,请重新输入')
return '下次再来'
return inner
@outer # index = outer(index)
def index(name):
print(f'性感荷官{name}在线发牌')
return '欢迎下次再来!'
index('jason')
@outer # home = outer(home)
def home(name):
print(f'大唐洗浴中心欢迎你,由{name}为您服务')
return '欢迎下次再来'
home('jason')
'''装饰器语法糖必须紧贴在被装饰对象的上面
装饰器语法糖的内部原理
会将紧贴在装饰器语法糖下面的函数名作为参数传递给装饰器函数
'''
![image]()
7.双层装饰器语法糖
import time
# 统计函数运行时间装饰器
def get_time(func):
# func = index
print('欢迎')
def inner1(*args,**kwargs):
# 获取被装饰对象函数运行之前的时间
start_time = time.time()
# 执行被装饰对象函数
res =func(*args,**kwargs)
# 获取被装饰对象函数运行之后的时间
end_time = time.time()
print(f'{end_time - start_time}')
return res
return inner1
is_login = {'is_login':False}
def login(func):
print('光临')
def inner2(*args,**kwargs):
# 判断用户的登录状态
if is_login.get('is_login'):
res = func(*args,**kwargs)
return res
# 获取用户的输入
user_name = input('输入你的登录名:').strip()
password = input('输入你的密码:').strip()
# 根据用户的输入进行比对
if user_name == 'jason' and password == '123':
# 如果成功了则调用函数并获取函数的返回值
res = func(*args,**kwargs)
# 用户登录成功,则修改登录的状态,不要再频繁登录
is_login['is_login'] = True
return res
print('登录名或者密码输入错误,请重新输入')
return '下次再来'
return inner2
@login # login(get_time(index)) = inner2 # index = inner2 # index() = inner2()
@get_time # get_time(index) = inner1
def index(name):
print(f'性感荷官{name}在线发牌')
return '欢迎下次再来!'
res = index('jason')
print(res)
print(index) # <function login.<locals>.inner2 at 0x0000029AA02A8168>
'''当出现多个装饰器语法糖连用时,先从和装饰器紧贴着的函数开始
由下往上依次调用,当最后一个装饰器语法糖上面不再有语法糖的时候,
用一个和被装饰对象名字相同的变量名接受装饰器的返回值
'''
![image]()
8.有参装饰器
import time
# 统计函数运行时间装饰器
def get_time(func):
# func = index
print('欢迎')
def inner1(*args,**kwargs):
# 获取被装饰对象函数运行之前的时间
start_time = time.time()
# 执行被装饰对象函数
res =func(*args,**kwargs)
# 获取被装饰对象函数运行之后的时间
end_time = time.time()
print(f'{end_time - start_time}')
return res
return inner1
is_login = {'is_login':False}
def login(func):
print('光临')
def inner2(*args,**kwargs):
# 判断用户的登录状态
if is_login.get('is_login'):
res = func(*args,**kwargs)
return res
# 获取用户的输入
user_name = input('输入你的登录名:').strip()
password = input('输入你的密码:').strip()
# 根据用户的输入进行比对
if user_name == 'jason' and password == '123':
# 如果成功了则调用函数并获取函数的返回值
res = func(*args,**kwargs)
# 用户登录成功,则修改登录的状态,不要再频繁登录
is_login['is_login'] = True
return res
print('登录名或者密码输入错误,请重新输入')
return '下次再来'
return inner2
@login # login(get_time(index)) = inner2 # index = inner2 # index() = inner2()
@get_time # get_time(index) = inner1
def index(name):
print(f'性感荷官{name}在线发牌')
return '欢迎下次再来!'
res = index('jason')
print(res)
print(index) # <function login.<locals>.inner2 at 0x0000029AA02A8168>
'''当出现多个装饰器语法糖连用时,先从和装饰器紧贴着的函数开始
由下往上依次调用,当最后一个装饰器语法糖上面不再有语法糖的时候,
用一个和被装饰对象名字相同的变量名接受装饰器的返回值
'''
![image]()