一. 编写函数,(函数执行的时间用time.sleep(n)模拟)
import time
def index(x, y, z):
time.sleep(1)
print('index is run...')
return x, y, z
二. 编写装饰器,为函数加上统计时间的功能
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print(f'{func.__name__} run time: ', stop_time - start_time)
return res
return wrapper
@timer # index = wrapper = timer(index)
def index(x, y, z):
time.sleep(1)
print('index is run...')
return x, y, z
res = index(1, 2, 3)
'''
index is run...
index run time: 1.0003461837768555
'''
print(res) # (1, 2, 3)
三. 编写装饰器,为函数加上认证的功能
import time
username = 'egon'
password = '123'
def login():
inp_username = input("输入用户名>>:").strip()
inp_password = input("输入用户密码>>:").strip()
if inp_username == username and inp_password == password:
print("恭喜登录成功!")
return inp_username
else:
print("登录失败!")
def auth(func):
def wrapper(*args, **kwargs):
username = login()
if username:
res = func(*args, **kwargs)
return res
return wrapper
@auth # index = wrapper = auth(index)
def index(x, y, z):
time.sleep(1)
print('index is run...')
return x, y, z
res = index(1, 2, 3)
print(res)
四. 编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
# 注意:从文件中读出字符串形式的字典,可以用eval('{"username":"egon","password":"123"}')转成字典格式
import time
import os
DB_PATH = r'db.txt'
login_state = None
def create_db():
if not os.path.isfile(DB_PATH):
with open(DB_PATH, mode='wt', encoding='utf-8') as f:
f.write('{"username":"egon","password":"123"}\n{"username":"alex","password":"123"}\n')
def read_db(name, pwd):
with open(DB_PATH, mode='rt', encoding='utf-8') as f:
for line in f:
res = line.strip()
if not res:
continue
current_user = eval(line)
username, password = current_user.values()
if name == username and password == pwd:
return name
def login():
create_db()
inp_username = input("输入用户名>>:").strip()
inp_password = input("输入用户密码>>:").strip()
res = read_db(inp_username, inp_password)
if res:
print("恭喜登录成功!")
global login_state
login_state = inp_username
return inp_username
else:
print("登录失败!")
def auth(func):
def wrapper(*args, **kwargs):
if not login_state:
login()
else:
res = func(*args, **kwargs)
return res
return wrapper
@auth # index = wrapper = auth(index)
def index(x, y, z):
time.sleep(1)
print('index is run...')
return x, y, z
@auth # home = wrapper = auth(home)
def home(x, y, z):
time.sleep(0.5)
print('home is run...')
return x, y, z
res = index(1, 2, 3)
print(res)
res = home(4, 5, 6)
print(res)
五. 编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录
import time
import os
DB_PATH = r'db.txt'
login_state = None
def create_db():
if not os.path.isfile(DB_PATH):
with open(DB_PATH, mode='wt', encoding='utf-8') as f:
f.write('{"username":"egon","password":"123"}\n{"username":"alex","password":"123"}\n')
def read_db(name, pwd):
with open(DB_PATH, mode='rt', encoding='utf-8') as f:
for line in f:
res = line.strip()
if not res:
continue
current_user = eval(line)
username, password = current_user.values()
if name == username and password == pwd:
return name
def login(*args):
create_db()
inp_username = input("输入用户名>>:").strip()
inp_password = input("输入用户密码>>:").strip()
res = read_db(inp_username, inp_password)
if res:
print("恭喜登录成功!")
global login_state
login_state = inp_username
return inp_username
else:
print("登录失败!")
def auth(func):
def wrapper(*args, **kwargs):
if not login_state:
login()
else:
res = func(*args, **kwargs)
return res
return wrapper
@auth # index = wrapper = auth(index)
def index(*args):
time.sleep(1)
print('index is run...')
return args
@auth # home = wrapper = auth(home)
def home(*args):
time.sleep(0.5)
print('home is run...')
return args
func_dic = {
'0': ('登录', login),
'1': ('index', index),
'2': ('home', home),
}
def run(*args, **kwargs):
while True:
for key, value in func_dic.items():
print(f'({key}):{value[0]}', end=' ')
print()
start_time = time.time()
cmd = input('输入命令编号>>:').strip()
stop_time = time.time()
if stop_time - start_time >= 4:
print('长时间没操作, 需要重新登录.')
global login_state
login_state = None
continue
if not cmd.isdigit():
print('请输入数字')
continue
if cmd not in func_dic:
print("输入命令编号范围不正确")
func_dic[cmd][1](*args, **kwargs)
res = run(1, 2, 3)
print(res)
六. 选做题
# 思考题(选做),叠加多个装饰器,加载顺序与运行顺序,可以将上述实现的装饰器叠加起来自己验证一下
"""
@deco1 # index=deco1(deco2.wrapper的内存地址)
@deco2 # deco2.wrapper的内存地址=deco2(deco3.wrapper的内存地址)
@deco3 # deco3.wrapper的内存地址=deco3(index)
def index():
pass
"""
def decorator1(func):
def wrapper(*args, **kwargs):
print('from decorator1')
res = func(*args, **kwargs)
return res
return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print('from decorator2')
res = func(*args, **kwargs)
return res
return wrapper
def decorator3(func):
def wrapper(*args, **kwargs):
print('from decorator3')
res = func(*args, **kwargs)
return res
return wrapper
@decorator1 # index = decorator1中的wrapper的内存地址 = decorator1(decorator2(decorator3(index)) )
@decorator2 # decorator2中的wrapper的内存地址 = decorator2(decorator3(index))
@decorator3 # decorator3中的wrapper的内存地址 = decorator3(index)
def index():
print('from index')
index()
'''
from decorator1
from decorator2
from decorator3
from index
'''
# 加载顺序: index > decorator3 > decorator2 > decorator1
# 运行顺序: decorator1 > decorator2 > decorator3 > index