Maison  >  Article  >  développement back-end  >  Exemple de partage de code sur la façon d'écrire un programme de panier d'achat en python

Exemple de partage de code sur la façon d'écrire un programme de panier d'achat en python

黄舟
黄舟original
2017-07-24 14:00:323710parcourir

要求

1、启动程序后,输入用户名密码后,如果是第一次登录,让用户输入工资,然后打印商品列表

2、允许用户根据商品编号购买商品

3、用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒

4、可随时退出,退出时,打印已购买商品和余额

5、在用户使用过程中, 关键输出,如余额,商品已加入购物车等消息,需高亮显示

6、用户下一次登录后,输入用户名密码,直接回到上次的状态,即上次消费的余额什么的还是那些,再次登录可继续购买

7、允许查询之前的消费记录


1)编写思路

编写思路参考下面GitHub链接中的流程图

2)具体实现

# -*- coding:utf-8 -*-

# Author:Chuixin Zeng

# 导入JSON模块
import json
# 导入日期时间模块
import datetime
# 导入系统OS模块
import os

# 自定义欢迎信息
info = '''
1. 按"A"注册
2. 按"B"登录
3. 按"Q"退出
'''
# 自定义错误提示信息
_error_info = '输入有误,请检查后重新输入!'

# 定义一个_save_account函数
# 用于将购物相关信息保存到JSON文件,比如购物时间,购物历史,购物列表,账户余额,创建的新用户和现有已存在用户信息
def _save_account(database, filename='DataBase.json'):
    # 打开并可写文件,若文件已存在,则以前的内容将被清除
    # 使用with as语句的效率更高,不需要单独设置如何读文件之后再如何关闭文件,一个with as搞定所有读写关闭操作
    with open(filename,'w') as f: # f相当于一个变量,把打开并修改文件的操作赋予f
        json.dump(database,f) # json.dump是将一个Python数据类型列表进行json格式的编码解析

# 定义一个_load_database函数,用于从json文件中读取信息,默认加载的数据库是database.json文件
def _load_database(filename='DataBase.json'):
    with open(filename) as f:
        database = json.load(f) # 解码JSON数据,将一个JSON编码的字符串转换回一个Python数据结构
    return database # 返回解码后的数据

# 定义一个函数_set_shopping_time,设置并记录购物的时间,函数里面定义了一个参数account,用于保存账户信息
def _set_shopping_time(account):
    database = _load_database() # 设定要记录到哪个数据库,这里使用的是前面定义好的函数_load_database定义的database.json
    d1 = datetime.datetime.now() # 设置购物时间为当前时间
    d2 = d1.strftime('%Y-%m-%d %H:%M:%S') # 将当前时间进行格式转换
    database[account]['shopping_time'] = d2 # 将转换好的时间记录到字典里面的shopping_time键上
    _save_account(database) # 保存购物时间到数据库中,这里的数据库是指database.json文件

# 定义一个函数,用于获取已经保存过的购物时间
def _get_datetime(account):
    database = _load_database()
    data = database[account]['shopping_time']
    # 返回变量data的值,变量data保存的就是account键对应的购物时间值,这个值是从json里面解码出来后到字典里
    # 由json到Python可识别的字典数据的解码过程由_load_database函数完成
    return data

# 定义一个函数_get_shopping_history,用于查询购物历史记录
def _get_shopping_history(account):
    database = _load_database()
    history = database[account]['shopping_list']
    # 增加一个空列表,配合下边for循环将购物清单中的重复项合并
    aa = []
    for i in history:
        # 将购物车里面的shopping list和aa空列表进行对比,如果列表里面没有,就添加到列表
        # 也就意味着,如果列表已经有了就不添加了,达到了购物车去重的功能
        if i not in aa:
            aa.append(i)
    # 然后循环遍历aa列表里面的购物清单
    for j in aa:
        # 统计购买的每件商品的数量,也就是aa列表里面每件商品的数量,数量从history原始列表里面取(未去重的列表)
        count = history.count(j)
        # 统计购买商品的日期,日期就是account字典对应的商品的日期
        date = _get_datetime(account)
        # 打印购买的商品的数量、日期和商品名称
        print('您于%s购买了%s件%s' %(date,count,j))

# 定义一个函数login,用于登录系统
def _login():
    database = _load_database() # 加载数据库,使用的是前面定义好的加载数据库的函数
    blacklist = _load_database('BlackList.json') # 设置用户的黑名单列表,在列表中的用户将不允许登录到购物系统
    print('欢迎登录购物系统!') # 打印欢迎信息
    # 第一个死循环
    while True:
        account = input("请输入您的账号登录系统(按q退出):")
        if account in blacklist:
            # 如果账户在黑名单里面,则退出登录
            print("您的账号已经被锁定,请联系管理员处理!")
            _logout() # 直接调用下面定义好的_logout()函数
        # 判断如果用户输入的是q,就退出购物系统
        elif account == 'q':
            _logout()
        # 判断如果用户在数据库里面,则继续判断用户输入的密码是否正确
        # 这里使用while循环和count计数器,如果输入错误密码大于3次,则锁定账户
        elif account in database:
            count = 0
            while count < 3:
                pwd = input(&#39;请输入密码:&#39;)
                # 如果用户输入的密码和数据库保存的密码匹配
                if pwd == database[account][&#39;pwd&#39;]:
                    # 进入到死循环
                    while True:
                        # 首先登录成功后,先获取用户账户的余额,告诉用户还剩多少钱,余额通过_get_balance函数得到
                        account_balance = _get_balance(account)
                        # 高亮打印账户的余额信息
                        print(&#39;您的账户余额是\033[32m%d\033[0m&#39;% account_balance)
                        # 让用户输入特定字母进入特定的菜单,并使用strip去除提示信息前后的空格
                        command = input(&#39;按h查询购物历史,按s开始购物,按t充值,开始购物后购物历史将被清空:&#39;).strip()
                        # 导入用户购物信息数据库
                        database = _load_database()
                        # 判断如果用户输入的是h,则查询购物历史
                        if command == &#39;h&#39;:
                            # 判断如果购物时间不为空的话,证明用户有购买历史
                            if database[account][&#39;shopping_time&#39;] != None:
                                # 加载函数_get_shopping_history,输出购物历史信息
                                _get_shopping_history(account)
                            else:
                                print(&#39;您在本商城没有购买过东西!&#39;)
                        elif command == &#39;t&#39;:
                            # 如果用户输入的是t,则加载定义好的_top_up函数,执行充值操作
                            _top_up(account)
                        elif command == &#39;s&#39;:
                            # 如果用户输入的是s,则将字典中的购物列表和时间初始化为空
                            # 注意:这个字典是从json文件转换过来的,里面有历史数据,所以需要先清空
                            # 等用户购物完成后,新的字典数据,即购物数据,会写回到json文件
                            database[account][&#39;shopping_list&#39;] = []
                            database[account][&#39;shopping_time&#39;] = None
                            # 调用_save_account函数,将清空的操作保存到database文件
                            _save_account(database)
                            # 调用shopping函数,开始购物
                            _shopping(account)
                        else:
                            # 如果用户的操作不符合上面所有的情况,则输出错误信息
                            # 这里直接调用前面定义好的_error_info函数,输出错误信息
                            print(_error_info)
                else:
                    count += 1
                    # 告诉用户还有多少次机会尝试登陆
                    print(&#39;输入的密码错误,你还有%s机会&#39; % (3 - count))
            # 将用户账号添加至blacklist,保存成字典形式,value设置为None
            # 这里使用了字典的setdefalut用法,如果字典中包含有给定键,则返回该键对应的值,否则返回为该键设置的值
            blacklist.setdefault(account)
            # 用户输入三次错误操作之后,会跳出上面的while循环,然后打印信息告诉用户账号已锁定
            print(&#39;您的账号已经锁定!&#39;)
            # 将锁定的账户信息保存到黑名单列表
            _save_account(blacklist,&#39;BlackList.json&#39;)
            # 调用退出登录的函数
            _logout()
        else:
            print(&#39;账号不存在,请重试!或输入b返回上一层,输入q,退出购物程序!&#39;)

# 定义一个函数_set_shopping_list,用于设定购物清单
def _set_shopping_list(account,c_name,num):
    database = _load_database()
    # 使用for循环添加购买的商品的数量
    for i in range(num):
        # 将购买的商品添加到字典shopping_list键所对应的列表中
        database[account][&#39;shopping_list&#39;].append(c_name)
        # 将购买信息通过调用_save_account函数保存到json文件中
        _save_account(database)

# 定义一个函数_set_balance,用于计算购买商品后,所剩下的余额
def _set_balance(account,num):
    database = _load_database()
    # 购买商品后,扣除购买的商品的价格
    database[account][&#39;balance&#39;] -= num
    # 将余额信息通过调用_save_account函数保存到json文件中
    _save_account(database)

# 定义一个函数,用于执行充值操作
def _top_up(account):
    database = _load_database()
    # 进入循环
    while True:
        # 提供交互式界面让用户输入要充值的金额
        num = input(&#39;请输入您要充值的金额:&#39;)
        # 判断如果用户输入的是不是纯数字,则将充值后的金额更新到数据库
        if num.isdigit():  # 判断输入是否为纯数字(充值的数据必须为纯数字)
            database[account]["balance"] += int(num)  # 将str格式的"纯数字"转换为int格式
            _save_account(database)  # 保存到文件
            account_balance = _get_balance(account)  # 再从文件中读取余额信息
            # 高亮打印充值后的余额信息
            print(&#39;您已成功充值,您的余额为\033[32m%d\033[0m元&#39; % account_balance)
            # 上面已经打印余额了,所以这里定义一个return none代表不使用return的方式返回余额
            return None

        # 如果用户输入的不是纯数字,则提示输入错误,重新进行while循环,让用户重新输入
        else:
            print(&#39;您的输入有误,请重新输入!&#39;)

# 定义一个函数_get_balance,用于获取账户余额
def _get_balance(account):
    database = _load_database()
    # 将字典中账户的余额信息读取到account_balance变量
    account_balance = database[account][&#39;balance&#39;]
    # 返回账户余额变量的值
    return account_balance

# 定义一个函数_shopping,用于执行购物程序
def _shopping(account):
    # 定义一个字典,用于保存商品菜单
    goods = {&#39;家电类&#39;: {&#39;电视&#39;: {&#39;小米电视&#39;: 3999, &#39;乐视电视&#39;: 4299},
                     &#39;空调&#39;: {&#39;格力空调&#39;: 8999, &#39;海尔空调&#39;: 6000},
                     &#39;冰箱&#39;: {&#39;美的冰箱&#39;: 5099, &#39;西门子冰箱&#39;: 4599}},
             &#39;3C类&#39;: {&#39;电脑&#39;: {&#39;联想笔记本&#39;: 6888, &#39;mac air&#39;: 8009},
                     &#39;手机&#39;: {&#39;小米5&#39;: 1999, &#39;iPhone6&#39;: 5299}},
             &#39;生活类&#39;: {&#39;鞋子&#39;: {&#39;NIKE篮球鞋&#39;: 899, &#39;安踏&#39;: 399},
                     &#39;T恤&#39;: {&#39;森马&#39;: 89, &#39;真维斯&#39;: 75, &#39;优衣库&#39;: 97}}}
    # 第一级死循环
    while True:
        # 通过使用enumerate来直接循环到产品名称
        for i in enumerate(goods.keys()):
            # 打印第一级菜单
            print(i)
        # 提供交互式界面,让用户输入要选择的商品分类名称,选择一级菜单
        choose = input(&#39;请输入您要选择的商品分类名称(输入q退出):&#39;).strip()
        # 定义一个空字符串,用于保存二级菜单
        str1 = &#39;&#39;
        if choose in goods:
            # 如果用户输入的商品分类正确,则将该商品分类下的所有商品打印出来
            for i in enumerate(goods[choose].keys()):
                # 打印用户选择的一级菜单下面的二级菜单
                print(i)
                # 将二级菜单追加添加到str1变量中
                str1 += (i[1] + &#39;\n&#39;)
            # 所有二级菜单均添加到str1之后,在str1后面加上:
            str1 += &#39;:&#39;
            # 第二级死循环
            while True:
                # 分类来自于前面choose的交互式输入,分类下面的列表来至于str1变量
                # 让用户选择一个二级菜单
                c_name = input("请输入您要选择的%s分类名称(输入b返回,输入q退出):\n%s"% (choose, str1)).strip()
                # 定义一个空字符串,用于保存三级菜单
                str2 = &#39;&#39;
                if c_name == &#39;b&#39;:
                    # 如果用户输入的是b,则中断当前的while循环,返回上上层循环,即返回到上层菜单
                    break
                elif c_name == &#39;q&#39;:
                    # 如果用户输入的是q,则调用_log_out函数,退出登录
                    _logout(account)
                # 如果用户输入的名称在二级菜单里面,则通过for把用户选择的二级菜单商品下面的三级菜单遍历出来
                elif c_name in goods[choose]:
                    for i in goods[choose][c_name].keys():
                        # 打印遍历出来的二级菜单下面的三级菜单,同时打印物品和价格
                        # i来自于keys即键名称(物品名称),goods[choose][c_name][i]取的是键的值,即价格
                        print(i,goods[choose][c_name][i])
                        str2 += (i + &#39;\n&#39;)
                    str2 += &#39;:&#39;
                    # 第三级死循环
                    while True:
                        # 在交互式界面,让用户输入要购买的商品的名称,商品目录来自于str2变量
                        p_name = input(&#39;请输入您要购买的商品名称(输入b返回上一级,q退出,h查询购物车):\n%s&#39;
                                       % str2).strip()
                        # 如果用户输入的是b,则跳出本层级的while死循环,退到上一级
                        if p_name == &#39;b&#39;:
                            break
                        # 如果用户输入的q,则直接调用_logout函数,退出购物
                        elif p_name == &#39;q&#39;:
                            _logout(account)
                        # 如果用户输入的h,则查询json文件中的购物历史
                        elif p_name == &#39;h&#39;:
                            database = _load_database()
                            # 有购物历史,则调用_get_shopping_history函数,输出购物历史
                            if database[account][&#39;shopping_time&#39;] != None:
                                _get_shopping_history()
                            # 梅花购物历史的话,则告诉用户无购物历史
                            else:
                                print(&#39;您在本商城没有购物记录!&#39;)
                        # 如果用户输入的商品名称在所选择的商品分类中
                        elif p_name in goods[choose][c_name]:
                            # 第四层死循环
                            while True:
                                # 交互式界面让用户输入要购买的商品的数量
                                num = input(&#39;请输入要购买的商品的数量:&#39;).strip()
                                # 如果用户输入的是纯数字
                                if num.isdigit():
                                    # 首先将纯数字转换为整型
                                    num = int(num)
                                    # 定义一个account_balance变量,保存现在的账户余额
                                    account_balance = _get_balance(account)
                                    # 定义一个价格变量,总价格 = 商品单价*数量,单价来自于字典,数量来自于num
                                    price = (goods[choose][c_name][p_name]) * num
                                    # 判断如果账户余额大于所购买的商品金额,才可以购买
                                    if account_balance >= price:
                                        # 调用_set_balance函数,计算购买后的账户余额是多少
                                        # #计算方法在_set_balance函数里面
                                        _set_balance(account,price)
                                        # 提示用户已经成功购买商品
                                        print(&#39;您成功购买%d件商品:%s!&#39;% (num,p_name))
                                        # 调用_set_shopping_list函数,将购买的商品列表保存到json文件中
                                        _set_shopping_list(account,p_name,num)
                                        # 定义account_balance变量,通过使用_get_balance函数重新获取账户的余额信息
                                        account_balance = _get_balance(account)
                                        # 打印告诉用户,购买完商品之后剩下多少钱
                                        print(&#39;您目前的账户余额为\033[31m%d\033[0m元&#39; % account_balance)
                                        # 调用_set_shopping_time函数,将购物时间写入到json文件
                                        _set_shopping_time(account)
                                        # 退出当前的循环,到上一级循环,用户可以选择是否继续购物
                                        break
                                    # 如果用户的账户余额小于商品的金额,则告诉用户余额不足,无法购买
                                    else:
                                        print(&#39;您的账户余额不足,请您及时充值!&#39;)
                                        g = input("充值输入t,返回上一级输入b,退出输入q&#39;:")
                                        if g == &#39;q&#39;:
                                            _logout()
                                        if g == &#39;b&#39;:
                                            break
                                        if g == &#39;t&#39;:
                                        # 这里我增加了一个调用_top_up函数,账户余额不住的时候,马上提示用户充值
                                            _top_up(account)
                                # 如果用户购买商品时输入的数量不是纯数字类型,则调用_error_info函数,输出错误信息
                                else:
                                    print(_error_info)
                        # 如果用户输入的购买的商品名称不正确,则调用_error_info函数,输出错误信息
                        else:
                            print(_error_info)
                # # 如果用户输入的购买的商品分类信息不正确,则调用_error_info函数,输出错误信息
                else:
                    print(&#39;输入错误,请重新输入!&#39;)
        # 如果用户输入的不是商品分类,而是q,则调用_logout函数退出登录
        elif choose == &#39;q&#39;:
            _logout(account)
        # 如果用户输入的信息既不在商品分类中,也不是q,则告诉用户重新输入
        else:
            print(&#39;输入错误,请重新输入!&#39;)

#
def _add_user():
    # 首先调用_load_database函数,将json文件解码出来,放到database变量
    database = _load_database(&#39;DataBase.json&#39;)
    # 执行while循环
    while True:
        # 提供交互式界面,让用户输入要创建的用户名称
        username = input(&#39;请输入您的账户名称:&#39;).strip()
        # 判断是否存在重名的用户,如果有,则告诉用户,继续执行while循环,让用户输入
        if username in database:
            print(&#39;用户名已经存在,不需要重复创建!&#39;)
        # 如果没有,则用户输入信息有效,中断while循环
        else:
            break
    # 执行while循环
    while True:
        # 让用户输入两次密码
        pwd1 = input(&#39;请输入您的账户密码:&#39;).strip()
        pwd2 = input(&#39;请再次输入您的账户密码:&#39;).strip()
        # 对两次输入的密码信息进行比对
        # 如果面膜不正确,则继续执行while循环让用户重新输入
        if pwd1 != pwd2:
            print(&#39;2次输入的密码不通,请重新输入&#39;)
        # 如果输入的密码是正确的,则告诉用户创建账户成功
        else:
            print(&#39;创建用户成功,开始购物吧!&#39;)
            # 把用户创建的账户和密码信息保存到database字典中
            # username为用户账号,pwd1为用户密码,balance为账户余额,shopping_list为购物清单,shopping_time为购物时间
            database[username] = {&#39;pwd&#39;:pwd1,&#39;balance&#39;:0,&#39;shopping_list&#39;:[],&#39;shopping_time&#39;:None}
            # 调用_save_account函数,将创建好的账户信息和账户的初始余额、初始购物时间信息保存到json文件
            _save_account(database)
            # 退出while循环
            break

# 设置默认变量account = None来判定账号是否已经登录,如果没有登录就退出,则不打印购物信息
# 如果已经登录过,则打印购物历史信息
def _logout(account=None):
    if account != None:
        _get_shopping_history(account)
    exit(&#39;感谢您来购物!&#39;)

# 定义一个main函数,用于初始登录界面的判断
def main():
    # 执行while循环
    while True:
        # 打印登录提示信息,info信息定义在程序的开头,是一个字符串类型
        print(info)
        # 提供交互式界面,让用户输入指令信息
        command = input(&#39;请输入指令:&#39;).strip()
        # 如果用户输入的是大写的A,则调用_add_user函数,创建新用户
        if command.upper() == &#39;A&#39;:
            _add_user()
        # 如果用户输入的是大写的B,则调用_login函数,进行登录
        elif command.upper() == &#39;B&#39;:
            _login()
        # 如果用户输入的是Q,则调用_logout函数,退出登录
        elif command.upper() == &#39;Q&#39;:
            _logout()
        # 如果用户没有按照提示信息进行输入,则告诉用户重新输入,会重新执行while循环
        else:
            print(&#39;输入错误,请重新输入&#39;)

# 执行main函数
if __name__ == &#39;__main__&#39;:
    main()



Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn