作业20200323
一:编写函数,(函数执行的时间用time.sleep(n)模拟)
二:编写装饰器,为函数加上统计时间的功能
三:编写装饰器,为函数加上认证的功能
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f'程序用时:{end - start}')
return res
return wrapper
def auth(func):
def login():
user_info = 'egon', '1234'
print('请登录')
name = input("name >>>:").strip()
pwd = input("pwd >>>:").strip()
if (name, pwd) == user_info:
print('登录成功')
return True
else:
print('登录失败')
return False
def wrapper(*args, **kwargs):
if login():
res = func(*args, **kwargs)
return res
return wrapper
@auth
@timer
def my_func():
time.sleep(2)
print('this is my_func')
if __name__ == '__main__':
my_func()
四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式
atm.py
def auth(func):
def wrapper(*args, **kwargs):
if current_user:
res = func(*args, **kwargs)
return res
else:
print('请先登录')
return wrapper
def login():
with open('db.txt', 'rt', encoding='utf8') as f:
name = input('name>>>:').strip()
pwd = input('pwd>>>:').strip()
for line in f:
n = eval(line.strip()).get('name')
p = eval(line.strip()).get('password')
if (name, pwd) == (n, p):
current_user.append(name)
print("登录成功")
break
else:
print('用户名或密码错误')
def logout():
print('欢迎下次再来')
exit()
@auth
def transfer():
print('this is transfer function')
@auth
def check_balance():
print('this is check_balance function')
current_user = []
def atm():
cmd_dict = {
'1': ('登录', login),
'2': ('查询余额', check_balance),
'3': ('转账', transfer),
'4': ('退出', logout),
}
while 1:
cmd = input("请选择功能的编号:").strip()
if cmd not in cmd_dict:
print('好好输入别闹')
continue
func = cmd_dict.get(cmd)[1]
func()
if __name__ == '__main__':
atm()
db.txt
{"name":"egon","password":"123"}
{"name":"tank","password":"123"}
五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录
import time
def timer(func):
def wrapper(*args, **kwargs):
now = int(time.time())
if now - current_user[1] < 20:
res = func(*args, **kwargs)
return res
else:
print('登录超时')
return wrapper
def auth(func):
def wrapper(*args, **kwargs):
if current_user[0]:
res = func(*args, **kwargs)
return res
else:
print('请先登录')
return wrapper
def login():
with open('db.txt', 'rt', encoding='utf8') as f:
name = input('name>>>:').strip()
pwd = input('pwd>>>:').strip()
for line in f:
n = eval(line.strip()).get('name')
p = eval(line.strip()).get('password')
if (name, pwd) == (n, p):
current_user[0:2] = [name, int(time.time())]
print("登录成功")
break
else:
print('用户名或密码错误')
def logout():
print('欢迎下次再来')
current_user.clear()
@auth
@timer
def transfer():
print('this is transfer function')
@auth
@timer
def check_balance():
print('this is check_balance function')
# 记录用户名和登录时间
current_user = [None, 0]
def atm():
cmd_dict = {
'1': ('登录', login),
'2': ('查询余额', check_balance),
'3': ('转账', transfer),
'4': ('退出', logout),
}
while 1:
cmd = input("请选择功能的编号:").strip()
if cmd not in cmd_dict:
print('好好输入别闹')
continue
func = cmd_dict.get(cmd)[1]
func()
if __name__ == '__main__':
atm()
db.txt
{"name":"egon","password":"123"}
{"name":"tank","password":"123"}
六:选做题
思考题(选做),叠加多个装饰器,加载顺序与运行顺序,可以将上述实现的装饰器叠加起来自己验证一下
def deco1(func):
def inner1(*args, **kwargs):
func1(*args, **kwargs)
return inner1
def deco2(func):
def inner2(*args, **kwargs):
func2(*args, **kwargs)
return inner2
def deco3(func):
def inner3(*args, **kwargs):
func3(*args, **kwargs)
return inner3
@deco1
@deco2
@deco3
def index():
pass
index()
# 上面语法糖的形式装饰器的本质就是:index = deco1(deco2(deco3(index))) (表达式1)
# 加载顺序:从下往上
# 执行顺序:从上往下
# 加载时:按照表达式1的顺序
- 首先,将被装饰函数index当实参传给deco3,返回deco3的inner3函数,
- 然后,返回的inner3当实参传给deco2,返回deco2的inner2函数,
- 最后,将返回的inner2当实参传给deco1,返回deco1的inner1,
# 加载完毕后,inner1的func1是inner2, inner2的func2是inner3, inner3的func3是index
# 运行时:index()
- 首先,执行index()本质是执行deco1返回的inner1()
- 然后, 执行inner1(),开始执行inner1内部的func1(func1指向inner2的内存地址),即开始执行inner2的内存地址上的函数,
- 再然后, 执行inner2(), 开始执行inner2内部的func2(func2指向inner3的内存地址),即开始执行inner3的内存地址上的函数,
- 最后,执行inner3(),开始执行inner3内部的func3(func3是最初的index),即执行index函数


浙公网安备 33010602011771号