• 老男孩Day2作业:编写购物车程序


    作业要求

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

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

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

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

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

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

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


    1)编写思路

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

    https://github.com/ChuixinZeng/PythonStudyCode/blob/master/PythonCode-OldBoy/Day2/作业/Day2_作业_购物车程序流程图.png


    2)具体实现

      1 # -*- coding:utf-8 -*-
      2 
      3 # Author:Chuixin Zeng
      4 
      5 # 导入JSON模块
      6 import json
      7 # 导入日期时间模块
      8 import datetime
      9 # 导入系统OS模块
     10 import os
     11 
     12 # 自定义欢迎信息
     13 info = '''
     14 1. 按"A"注册
     15 2. 按"B"登录
     16 3. 按"Q"退出
     17 '''
     18 # 自定义错误提示信息
     19 _error_info = '输入有误,请检查后重新输入!'
     20 
     21 # 定义一个_save_account函数
     22 # 用于将购物相关信息保存到JSON文件,比如购物时间,购物历史,购物列表,账户余额,创建的新用户和现有已存在用户信息
     23 def _save_account(database, filename='DataBase.json'):
     24     # 打开并可写文件,若文件已存在,则以前的内容将被清除
     25     # 使用with as语句的效率更高,不需要单独设置如何读文件之后再如何关闭文件,一个with as搞定所有读写关闭操作
     26     with open(filename,'w') as f: # f相当于一个变量,把打开并修改文件的操作赋予f
     27         json.dump(database,f) # json.dump是将一个Python数据类型列表进行json格式的编码解析
     28 
     29 # 定义一个_load_database函数,用于从json文件中读取信息,默认加载的数据库是database.json文件
     30 def _load_database(filename='DataBase.json'):
     31     with open(filename) as f:
     32         database = json.load(f) # 解码JSON数据,将一个JSON编码的字符串转换回一个Python数据结构
     33     return database # 返回解码后的数据
     34 
     35 # 定义一个函数_set_shopping_time,设置并记录购物的时间,函数里面定义了一个参数account,用于保存账户信息
     36 def _set_shopping_time(account):
     37     database = _load_database() # 设定要记录到哪个数据库,这里使用的是前面定义好的函数_load_database定义的database.json
     38     d1 = datetime.datetime.now() # 设置购物时间为当前时间
     39     d2 = d1.strftime('%Y-%m-%d %H:%M:%S') # 将当前时间进行格式转换
     40     database[account]['shopping_time'] = d2 # 将转换好的时间记录到字典里面的shopping_time键上
     41     _save_account(database) # 保存购物时间到数据库中,这里的数据库是指database.json文件
     42 
     43 # 定义一个函数,用于获取已经保存过的购物时间
     44 def _get_datetime(account):
     45     database = _load_database()
     46     data = database[account]['shopping_time']
     47     # 返回变量data的值,变量data保存的就是account键对应的购物时间值,这个值是从json里面解码出来后到字典里
     48     # 由json到Python可识别的字典数据的解码过程由_load_database函数完成
     49     return data
     50 
     51 # 定义一个函数_get_shopping_history,用于查询购物历史记录
     52 def _get_shopping_history(account):
     53     database = _load_database()
     54     history = database[account]['shopping_list']
     55     # 增加一个空列表,配合下边for循环将购物清单中的重复项合并
     56     aa = []
     57     for i in history:
     58         # 将购物车里面的shopping list和aa空列表进行对比,如果列表里面没有,就添加到列表
     59         # 也就意味着,如果列表已经有了就不添加了,达到了购物车去重的功能
     60         if i not in aa:
     61             aa.append(i)
     62     # 然后循环遍历aa列表里面的购物清单
     63     for j in aa:
     64         # 统计购买的每件商品的数量,也就是aa列表里面每件商品的数量,数量从history原始列表里面取(未去重的列表)
     65         count = history.count(j)
     66         # 统计购买商品的日期,日期就是account字典对应的商品的日期
     67         date = _get_datetime(account)
     68         # 打印购买的商品的数量、日期和商品名称
     69         print('您于%s购买了%s件%s' %(date,count,j))
     70 
     71 # 定义一个函数login,用于登录系统
     72 def _login():
     73     database = _load_database() # 加载数据库,使用的是前面定义好的加载数据库的函数
     74     blacklist = _load_database('BlackList.json') # 设置用户的黑名单列表,在列表中的用户将不允许登录到购物系统
     75     print('欢迎登录购物系统!') # 打印欢迎信息
     76     # 第一个死循环
     77     while True:
     78         account = input("请输入您的账号登录系统(按q退出):")
     79         if account in blacklist:
     80             # 如果账户在黑名单里面,则退出登录
     81             print("您的账号已经被锁定,请联系管理员处理!")
     82             _logout() # 直接调用下面定义好的_logout()函数
     83         # 判断如果用户输入的是q,就退出购物系统
     84         elif account == 'q':
     85             _logout()
     86         # 判断如果用户在数据库里面,则继续判断用户输入的密码是否正确
     87         # 这里使用while循环和count计数器,如果输入错误密码大于3次,则锁定账户
     88         elif account in database:
     89             count = 0
     90             while count < 3:
     91                 pwd = input('请输入密码:')
     92                 # 如果用户输入的密码和数据库保存的密码匹配
     93                 if pwd == database[account]['pwd']:
     94                     # 进入到死循环
     95                     while True:
     96                         # 首先登录成功后,先获取用户账户的余额,告诉用户还剩多少钱,余额通过_get_balance函数得到
     97                         account_balance = _get_balance(account)
     98                         # 高亮打印账户的余额信息
     99                         print('您的账户余额是33[32m%d33[0m'% account_balance)
    100                         # 让用户输入特定字母进入特定的菜单,并使用strip去除提示信息前后的空格
    101                         command = input('按h查询购物历史,按s开始购物,按t充值,开始购物后购物历史将被清空:').strip()
    102                         # 导入用户购物信息数据库
    103                         database = _load_database()
    104                         # 判断如果用户输入的是h,则查询购物历史
    105                         if command == 'h':
    106                             # 判断如果购物时间不为空的话,证明用户有购买历史
    107                             if database[account]['shopping_time'] != None:
    108                                 # 加载函数_get_shopping_history,输出购物历史信息
    109                                 _get_shopping_history(account)
    110                             else:
    111                                 print('您在本商城没有购买过东西!')
    112                         elif command == 't':
    113                             # 如果用户输入的是t,则加载定义好的_top_up函数,执行充值操作
    114                             _top_up(account)
    115                         elif command == 's':
    116                             # 如果用户输入的是s,则将字典中的购物列表和时间初始化为空
    117                             # 注意:这个字典是从json文件转换过来的,里面有历史数据,所以需要先清空
    118                             # 等用户购物完成后,新的字典数据,即购物数据,会写回到json文件
    119                             database[account]['shopping_list'] = []
    120                             database[account]['shopping_time'] = None
    121                             # 调用_save_account函数,将清空的操作保存到database文件
    122                             _save_account(database)
    123                             # 调用shopping函数,开始购物
    124                             _shopping(account)
    125                         else:
    126                             # 如果用户的操作不符合上面所有的情况,则输出错误信息
    127                             # 这里直接调用前面定义好的_error_info函数,输出错误信息
    128                             print(_error_info)
    129                 else:
    130                     count += 1
    131                     # 告诉用户还有多少次机会尝试登陆
    132                     print('输入的密码错误,你还有%s机会' % (3 - count))
    133             # 将用户账号添加至blacklist,保存成字典形式,value设置为None
    134             # 这里使用了字典的setdefalut用法,如果字典中包含有给定键,则返回该键对应的值,否则返回为该键设置的值
    135             blacklist.setdefault(account)
    136             # 用户输入三次错误操作之后,会跳出上面的while循环,然后打印信息告诉用户账号已锁定
    137             print('您的账号已经锁定!')
    138             # 将锁定的账户信息保存到黑名单列表
    139             _save_account(blacklist,'BlackList.json')
    140             # 调用退出登录的函数
    141             _logout()
    142         else:
    143             print('账号不存在,请重试!或输入b返回上一层,输入q,退出购物程序!')
    144 
    145 # 定义一个函数_set_shopping_list,用于设定购物清单
    146 def _set_shopping_list(account,c_name,num):
    147     database = _load_database()
    148     # 使用for循环添加购买的商品的数量
    149     for i in range(num):
    150         # 将购买的商品添加到字典shopping_list键所对应的列表中
    151         database[account]['shopping_list'].append(c_name)
    152         # 将购买信息通过调用_save_account函数保存到json文件中
    153         _save_account(database)
    154 
    155 # 定义一个函数_set_balance,用于计算购买商品后,所剩下的余额
    156 def _set_balance(account,num):
    157     database = _load_database()
    158     # 购买商品后,扣除购买的商品的价格
    159     database[account]['balance'] -= num
    160     # 将余额信息通过调用_save_account函数保存到json文件中
    161     _save_account(database)
    162 
    163 # 定义一个函数,用于执行充值操作
    164 def _top_up(account):
    165     database = _load_database()
    166     # 进入循环
    167     while True:
    168         # 提供交互式界面让用户输入要充值的金额
    169         num = input('请输入您要充值的金额:')
    170         # 判断如果用户输入的是不是纯数字,则将充值后的金额更新到数据库
    171         if num.isdigit():  # 判断输入是否为纯数字(充值的数据必须为纯数字)
    172             database[account]["balance"] += int(num)  # 将str格式的"纯数字"转换为int格式
    173             _save_account(database)  # 保存到文件
    174             account_balance = _get_balance(account)  # 再从文件中读取余额信息
    175             # 高亮打印充值后的余额信息
    176             print('您已成功充值,您的余额为33[32m%d33[0m元' % account_balance)
    177             # 上面已经打印余额了,所以这里定义一个return none代表不使用return的方式返回余额
    178             return None
    179 
    180         # 如果用户输入的不是纯数字,则提示输入错误,重新进行while循环,让用户重新输入
    181         else:
    182             print('您的输入有误,请重新输入!')
    183 
    184 # 定义一个函数_get_balance,用于获取账户余额
    185 def _get_balance(account):
    186     database = _load_database()
    187     # 将字典中账户的余额信息读取到account_balance变量
    188     account_balance = database[account]['balance']
    189     # 返回账户余额变量的值
    190     return account_balance
    191 
    192 # 定义一个函数_shopping,用于执行购物程序
    193 def _shopping(account):
    194     # 定义一个字典,用于保存商品菜单
    195     goods = {'家电类': {'电视': {'小米电视': 3999, '乐视电视': 4299},
    196                      '空调': {'格力空调': 8999, '海尔空调': 6000},
    197                      '冰箱': {'美的冰箱': 5099, '西门子冰箱': 4599}},
    198              '3C类': {'电脑': {'联想笔记本': 6888, 'mac air': 8009},
    199                      '手机': {'小米5': 1999, 'iPhone6': 5299}},
    200              '生活类': {'鞋子': {'NIKE篮球鞋': 899, '安踏': 399},
    201                      'T恤': {'森马': 89, '真维斯': 75, '优衣库': 97}}}
    202     # 第一级死循环
    203     while True:
    204         # 通过使用enumerate来直接循环到产品名称
    205         for i in enumerate(goods.keys()):
    206             # 打印第一级菜单
    207             print(i)
    208         # 提供交互式界面,让用户输入要选择的商品分类名称,选择一级菜单
    209         choose = input('请输入您要选择的商品分类名称(输入q退出):').strip()
    210         # 定义一个空字符串,用于保存二级菜单
    211         str1 = ''
    212         if choose in goods:
    213             # 如果用户输入的商品分类正确,则将该商品分类下的所有商品打印出来
    214             for i in enumerate(goods[choose].keys()):
    215                 # 打印用户选择的一级菜单下面的二级菜单
    216                 print(i)
    217                 # 将二级菜单追加添加到str1变量中
    218                 str1 += (i[1] + '
    ')
    219             # 所有二级菜单均添加到str1之后,在str1后面加上:
    220             str1 += ':'
    221             # 第二级死循环
    222             while True:
    223                 # 分类来自于前面choose的交互式输入,分类下面的列表来至于str1变量
    224                 # 让用户选择一个二级菜单
    225                 c_name = input("请输入您要选择的%s分类名称(输入b返回,输入q退出):
    %s"% (choose, str1)).strip()
    226                 # 定义一个空字符串,用于保存三级菜单
    227                 str2 = ''
    228                 if c_name == 'b':
    229                     # 如果用户输入的是b,则中断当前的while循环,返回上上层循环,即返回到上层菜单
    230                     break
    231                 elif c_name == 'q':
    232                     # 如果用户输入的是q,则调用_log_out函数,退出登录
    233                     _logout(account)
    234                 # 如果用户输入的名称在二级菜单里面,则通过for把用户选择的二级菜单商品下面的三级菜单遍历出来
    235                 elif c_name in goods[choose]:
    236                     for i in goods[choose][c_name].keys():
    237                         # 打印遍历出来的二级菜单下面的三级菜单,同时打印物品和价格
    238                         # i来自于keys即键名称(物品名称),goods[choose][c_name][i]取的是键的值,即价格
    239                         print(i,goods[choose][c_name][i])
    240                         str2 += (i + '
    ')
    241                     str2 += ':'
    242                     # 第三级死循环
    243                     while True:
    244                         # 在交互式界面,让用户输入要购买的商品的名称,商品目录来自于str2变量
    245                         p_name = input('请输入您要购买的商品名称(输入b返回上一级,q退出,h查询购物车):
    %s'
    246                                        % str2).strip()
    247                         # 如果用户输入的是b,则跳出本层级的while死循环,退到上一级
    248                         if p_name == 'b':
    249                             break
    250                         # 如果用户输入的q,则直接调用_logout函数,退出购物
    251                         elif p_name == 'q':
    252                             _logout(account)
    253                         # 如果用户输入的h,则查询json文件中的购物历史
    254                         elif p_name == 'h':
    255                             database = _load_database()
    256                             # 有购物历史,则调用_get_shopping_history函数,输出购物历史
    257                             if database[account]['shopping_time'] != None:
    258                                 _get_shopping_history()
    259                             # 梅花购物历史的话,则告诉用户无购物历史
    260                             else:
    261                                 print('您在本商城没有购物记录!')
    262                         # 如果用户输入的商品名称在所选择的商品分类中
    263                         elif p_name in goods[choose][c_name]:
    264                             # 第四层死循环
    265                             while True:
    266                                 # 交互式界面让用户输入要购买的商品的数量
    267                                 num = input('请输入要购买的商品的数量:').strip()
    268                                 # 如果用户输入的是纯数字
    269                                 if num.isdigit():
    270                                     # 首先将纯数字转换为整型
    271                                     num = int(num)
    272                                     # 定义一个account_balance变量,保存现在的账户余额
    273                                     account_balance = _get_balance(account)
    274                                     # 定义一个价格变量,总价格 = 商品单价*数量,单价来自于字典,数量来自于num
    275                                     price = (goods[choose][c_name][p_name]) * num
    276                                     # 判断如果账户余额大于所购买的商品金额,才可以购买
    277                                     if account_balance >= price:
    278                                         # 调用_set_balance函数,计算购买后的账户余额是多少
    279                                         # #计算方法在_set_balance函数里面
    280                                         _set_balance(account,price)
    281                                         # 提示用户已经成功购买商品
    282                                         print('您成功购买%d件商品:%s!'% (num,p_name))
    283                                         # 调用_set_shopping_list函数,将购买的商品列表保存到json文件中
    284                                         _set_shopping_list(account,p_name,num)
    285                                         # 定义account_balance变量,通过使用_get_balance函数重新获取账户的余额信息
    286                                         account_balance = _get_balance(account)
    287                                         # 打印告诉用户,购买完商品之后剩下多少钱
    288                                         print('您目前的账户余额为33[31m%d33[0m元' % account_balance)
    289                                         # 调用_set_shopping_time函数,将购物时间写入到json文件
    290                                         _set_shopping_time(account)
    291                                         # 退出当前的循环,到上一级循环,用户可以选择是否继续购物
    292                                         break
    293                                     # 如果用户的账户余额小于商品的金额,则告诉用户余额不足,无法购买
    294                                     else:
    295                                         print('您的账户余额不足,请您及时充值!')
    296                                         g = input("充值输入t,返回上一级输入b,退出输入q':")
    297                                         if g == 'q':
    298                                             _logout()
    299                                         if g == 'b':
    300                                             break
    301                                         if g == 't':
    302                                         # 这里我增加了一个调用_top_up函数,账户余额不住的时候,马上提示用户充值
    303                                             _top_up(account)
    304                                 # 如果用户购买商品时输入的数量不是纯数字类型,则调用_error_info函数,输出错误信息
    305                                 else:
    306                                     print(_error_info)
    307                         # 如果用户输入的购买的商品名称不正确,则调用_error_info函数,输出错误信息
    308                         else:
    309                             print(_error_info)
    310                 # # 如果用户输入的购买的商品分类信息不正确,则调用_error_info函数,输出错误信息
    311                 else:
    312                     print('输入错误,请重新输入!')
    313         # 如果用户输入的不是商品分类,而是q,则调用_logout函数退出登录
    314         elif choose == 'q':
    315             _logout(account)
    316         # 如果用户输入的信息既不在商品分类中,也不是q,则告诉用户重新输入
    317         else:
    318             print('输入错误,请重新输入!')
    319 
    320 #
    321 def _add_user():
    322     # 首先调用_load_database函数,将json文件解码出来,放到database变量
    323     database = _load_database('DataBase.json')
    324     # 执行while循环
    325     while True:
    326         # 提供交互式界面,让用户输入要创建的用户名称
    327         username = input('请输入您的账户名称:').strip()
    328         # 判断是否存在重名的用户,如果有,则告诉用户,继续执行while循环,让用户输入
    329         if username in database:
    330             print('用户名已经存在,不需要重复创建!')
    331         # 如果没有,则用户输入信息有效,中断while循环
    332         else:
    333             break
    334     # 执行while循环
    335     while True:
    336         # 让用户输入两次密码
    337         pwd1 = input('请输入您的账户密码:').strip()
    338         pwd2 = input('请再次输入您的账户密码:').strip()
    339         # 对两次输入的密码信息进行比对
    340         # 如果面膜不正确,则继续执行while循环让用户重新输入
    341         if pwd1 != pwd2:
    342             print('2次输入的密码不通,请重新输入')
    343         # 如果输入的密码是正确的,则告诉用户创建账户成功
    344         else:
    345             print('创建用户成功,开始购物吧!')
    346             # 把用户创建的账户和密码信息保存到database字典中
    347             # username为用户账号,pwd1为用户密码,balance为账户余额,shopping_list为购物清单,shopping_time为购物时间
    348             database[username] = {'pwd':pwd1,'balance':0,'shopping_list':[],'shopping_time':None}
    349             # 调用_save_account函数,将创建好的账户信息和账户的初始余额、初始购物时间信息保存到json文件
    350             _save_account(database)
    351             # 退出while循环
    352             break
    353 
    354 # 设置默认变量account = None来判定账号是否已经登录,如果没有登录就退出,则不打印购物信息
    355 # 如果已经登录过,则打印购物历史信息
    356 def _logout(account=None):
    357     if account != None:
    358         _get_shopping_history(account)
    359     exit('感谢您来购物!')
    360 
    361 # 定义一个main函数,用于初始登录界面的判断
    362 def main():
    363     # 执行while循环
    364     while True:
    365         # 打印登录提示信息,info信息定义在程序的开头,是一个字符串类型
    366         print(info)
    367         # 提供交互式界面,让用户输入指令信息
    368         command = input('请输入指令:').strip()
    369         # 如果用户输入的是大写的A,则调用_add_user函数,创建新用户
    370         if command.upper() == 'A':
    371             _add_user()
    372         # 如果用户输入的是大写的B,则调用_login函数,进行登录
    373         elif command.upper() == 'B':
    374             _login()
    375         # 如果用户输入的是Q,则调用_logout函数,退出登录
    376         elif command.upper() == 'Q':
    377             _logout()
    378         # 如果用户没有按照提示信息进行输入,则告诉用户重新输入,会重新执行while循环
    379         else:
    380             print('输入错误,请重新输入')
    381 
    382 # 执行main函数
    383 if __name__ == '__main__':
    384     main()

    3)Github笔记

    第二天的笔记的地址是:

    https://github.com/ChuixinZeng/PythonStudyCode/tree/master/PythonCode-OldBoy/Day2/随堂练习

    第二天作业的地址是:

    https://github.com/ChuixinZeng/PythonStudyCode/tree/master/PythonCode-OldBoy/Day2/作业


    4)Readme.md文档

    https://github.com/ChuixinZeng/PythonStudyCode/blob/master/PythonCode-OldBoy/Day2/作业/Day2_作业_购物车程序Readme.md

  • 相关阅读:
    Docker 日志都在哪里?怎么收集?
    docker link 过时不再用了?那容器互联、服务发现怎么办?
    Centos7.0 配置docker 镜像加速
    使用docker搭建公司redmine服务器
    Jenkins pipeline:pipeline 使用之语法详解
    Xcode脚本自动化打包问题:xcrun: error: unable to find utility "PackageApplication", not a developer tool or in PATH
    java基础(7)---IO流
    java基础(6)---面向对象,类,包
    java基础(5)---内存分配
    java基础(4)---引用数据类型(数组、字符串、集合)
  • 原文地址:https://www.cnblogs.com/ChuixinZeng/p/JamieZeng_Day2.html
Copyright © 2020-2023  润新知