python函数与装饰器的综合应用

1、需求:

编写小说阅读程序实现下属功能
# 一:程序运行开始时显示
    0 账号注册
    1 充值功能
    2 阅读小说


# 二: 针对文件db.txt,内容格式为:"用户名:密码:金额",完成下述功能
2.1、账号注册
2.2、充值功能

# 三:文件story_class.txt存放类别与小说文件路径,如下,读出来后可用eval反解出字典
{"0":{"0":["倚天屠狗记.txt",3],"1":["沙雕英雄转.txt",10]},"1":{"0":["令人羞耻的爱.txt",6],"1":["二狗的妻子与大草原的故事.txt",5]},}

3.1、用户登录成功后显示如下内容,根据用户选择,显示对应品类的小说编号、小说名字、以及小说的价格
"""
0 玄幻武侠
1 都市爱情
2 高效养猪36技
"""

3.2、用户输入具体的小说编号,提示是否付费,用户输入y确定后,扣费并显示小说内容,如果余额不足则提示余额不足

# 四:为功能2.2、3.1、3.2编写认证功能装饰器,要求必须登录后才能执行操作

# 五:为功能2.2、3.2编写记录日志的装饰器,日志格式为:"时间 用户名 操作(充值or消费) 金额"

2、代码

"""
分析:我们设置四个主体功能,账号注册,充值,购买小说,登录认证,显然登录认证功能要用装饰器编写
"""

from functools import wraps
import os

# 注册功能
def register(user_name, password):
    with open(r'用户信息.txt', mode='at', encoding='utf-8') as f:
        f.write(str(user_name))
        f.write(':')
        f.write(str(password))
        f.write(':')
        f.write('0')
        f.write('\n')
        print('注册成功')


# 登录认证装饰器
def auth(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        in_user_name = input('请输入你的账号>>>>>>>')
        in_user_password = input('请输入密码>>>>>>>')

        with open(r'用户信息.txt', mode='rt', encoding='utf-8') as f:
            for line in f:
                username, password, money = line.strip('\n').split(':')
                if in_user_name == username and in_user_password == password:
                    print('登录认证成功')
                    f.close()
                    res = func(*args, **kwargs)
                    return res
            else:
                    print('验证失败,账号或密码错误')

    return wrapper


# 充值功能
@auth
def recharge(user_name, money):
    with open(r'用户信息.txt', mode='rt', encoding='utf-8') as f1, \
            open(r'用户信息.txt.swap', mode='wt', encoding='utf-8') as f2:
        for line in f1:
            username, password, original_money = line.strip('\n').split(':')
            if username == user_name:
                new_balance = int(original_money) + int(money)
                f2.write(f"{username}:{password}:{new_balance}")
                print('充值成功,余额已经更新')
            else:
                f2.write(line)
    os.remove(r'用户信息.txt')
    os.rename(r'用户信息.txt.swap', r'用户信息.txt')


# 阅读与购买功能
@auth
def shopping(user_name, cost):
    with open(r'用户信息.txt', mode='rt', encoding='utf-8') as f1, \
            open(r'用户信息.txt.swap', mode='wt', encoding='utf-8') as f2:
        for line in f1:
            username, password, original_money = line.strip('\n').split(':')
            if username == user_name:
                new_balance = int(original_money) - int(cost)
                f2.write(f"{username}:{password}:{new_balance}")
                print('购买成功,余额已更新,请及时查询')
            else:
                f2.write(line)
    os.remove(r'用户信息.txt')
    os.rename(r'用户信息.txt.swap', r'用户信息.txt')


# 菜单
print(' 0 账号注册>>>>> \n 1 充值>>>>>>>> \n 2 购买书籍>>>>>\n-1 退出')

# 主控制程序
while True:
    cmd = input('请输入指令')
    if cmd == '-1':
        break
    elif cmd == '0':
        input_username = input('请输入注册用户名>>>>>').strip()
        input_password = input('请输入注册密码>>>>>>>').strip()
        register(input_username, input_password)
    elif cmd == '1':
        input_username = input('请输入充值用户名>>>>>').strip()
        input_recharge_number = input('请输入充值金额>>>>>>>').strip()
        recharge(input_username, input_recharge_number)
    elif cmd == '2':
        with open(r'书籍仓库.txt', mode='rt', encoding='utf-8') as f:
            res = f.read()
            book_dict = eval(res)
            print("0 玄幻武侠\n1 都市爱情\n2 高效养猪36技")
            Type = input("请输入你想购买的小说类型编号:").strip()
            print(book_dict[Type])
            book = input("请输入你想购买的小说编号:").strip()
            print(book_dict[Type][book])
            book_cost = int(book_dict[Type][book][1])
            input_username = input('请确认您的用户名')
            shopping(input_username, book_cost)

3、总结

代码能力还是不足,对需求的实现有些地方过于冗余,再接再厉。

上一篇:【Java】Springboot使用Redisson配置


下一篇:thinkphp6: 用bcrypt加密生成密码(php 8.1.1 / thinkphp v6.0.10LTS )