# 代码实现: 购物车
# 功能要求: 1.用户输入总资产,例如:2000.
# 2.显示商品列表,让用户根据序号选择商品,加入购物车购买
# 3.如果商品总额大于总资产,提示账户余额不足,否则,购买成功
# 额外功能: 1.支持 一次购买多种商品多个数目
# 2.支持 多次购买
# 3.支持 在用户继续购买时显示商品库存
# 4.支持 在选择商品时输入任意字符,但必须是"商品编号:购买数量"的格式
# 5.支持 判断初始资产是否可以买到最低单价的商品,以及购买后钱包余额是否可以继续挑选商品,如不够则提示用户
# 6.支持 选择的商品数量超出库存时自动修改为最大库存量,并提示用户所选商品名和修改后的最大库存数目
# 7.支持 购买后显示用户买了哪些商品,单价多少,数量多少,单种商品花费多少,总花费及余额
# 8.支持 选择的商品总价大于资产数时,显示需补充的差价
# 9.支持 商品售空时再次显示时自动删除该商品(不显示该条目)
# 10.支持 判断连续购买的次数并在用户选择结束购买时显示"谢谢%d次惠顾
# 11.如需添加录入新商品的功能,可用以下代码实现:
# 12.还可添加一项: 将商品列表添加到本地json文件/服务器数据库等
1 def format_insert_words_and_add_good_info(insert_words, separator_symbol): 2 insert_words_formatted_list = insert_words.split(separator_symbol) 3 # 此处省略类似下面select_goods()函数里的格式化输入的步骤,自动删除所有不合法的输入 4 # 以下代码默认good_insert的内容为合法内容,且省略了商品名已存在时修改录入的商品名为'商品1'的步骤 5 good_temp_dic = {"name": insert_words_formatted_list[0], "price": int(insert_words_formatted_list[1]), 6 "allowance": int(insert_words_formatted_list[2])} 7 goods.append(good_temp_dic) 8 return goods 9 10 11 def show_insert(): 12 try: 13 good_insert = input("请输入准备添加到货架的商品的'名字','单价','数量',用英文逗号/英文句号或空格隔开: ").strip() 14 if ',' in good_insert: 15 format_insert_words_and_add_good_info(good_insert, ',') 16 elif '.' in good_insert: 17 format_insert_words_and_add_good_info(good_insert, '.') 18 elif ' ' in good_insert: 19 format_insert_words_and_add_good_info(good_insert, ' ') 20 else: 21 print('分隔符输入不合法,未能录入数据') 22 show_insert() 23 except KeyboardInterrupt: 24 print('\n手动终止录入进程,再见...') 25 26 def write_goods_info(): 27 show_insert() 28 with open('goods_info.json','w') as info_file: 29 # 这里如果用遍历goods的方法,只添加商品的字典,那么在上面'格式化插入的文字以及添加商品信息'方法里直接追加good_temp_dic 30 # with open('goods_info.json','a') as info_file: 31 info_file.write(goods) 32
额外功能实现代码如下
1 goods = [{"name": "电脑", "price": 1999, "allowance": 100}, 2 {"name": "鼠标", "price": 10, "allowance": 100}, 3 {"name": "游艇", "price": 20, "allowance": 100}, 4 {"name": "美女", "price": 998, "allowance": 100}, 5 {"name": "帅哥", "price": 98, "allowance": 100}, ] 6 price_list = [] # 方便后面比较钱包余额是否大于最小单价 7 for good_index_temp in range(0, len(goods)): price_list.append(goods[good_index_temp]['price']) 8 9 10 def show_goods(): 11 print('**********商品列表**********') 12 print('编号\t\t商品\t\t价格\t\t库存') 13 for good_index in range(0, len(goods)): 14 good_index += 1 15 print('{0}\t\t{1}\t\t{2}\t\t{3}'.format(good_index, goods[good_index - 1]['name'], 16 goods[good_index - 1]['price'], 17 goods[good_index - 1]['allowance'])) 18 19 20 def show_wallet(): 21 wallet = input('偷偷show一下钱包金额:').strip() 22 if wallet.isdigit(): 23 wallet = int(wallet) 24 if wallet < min(price_list): 25 print('穷逼滚,再给你一次机会') 26 show_wallet() 27 else: 28 print('总资产%d元,开始购物吧高富帅' % wallet) 29 return wallet 30 else: 31 print('糊弄谁呢?再给你一次机会') 32 show_wallet() 33 34 35 def select_goods(wallet, shopping_count=0): # return customer_choice_list, return selected_goods 36 customer_choice = input("请选择商品编号及数量(以':'区分),使用空格隔开: ") 37 # ' 4:3:4 3:2 5:1 a:1 %:# # @ 1:120 2:m '' 38 customer_choice_list = customer_choice.split(' ') 39 print(customer_choice_list) 40 temp_list = customer_choice_list.copy() # 浅拷贝,以便后面遍历时删除无效项或非法项 41 for element in temp_list: 42 if element == '' or element == ' ': # 去空(无效项) 43 # print('过多的空格已被自动删除') 44 customer_choice_list.remove(element) 45 elif ':' not in element: # 去掉无":"匹配的项(无效项) 46 # print('无效的匹配项已被自动删除') 47 customer_choice_list.remove(element) 48 elif len(element.split(':')) != 2: # 去掉":"匹配后长度不为2(不是正常匹配)的项目(非法项) 49 # print('非法项已被自动删除') 50 customer_choice_list.remove(element) 51 elif element.split(':')[0].isdigit() == 0 or element.split(':')[-1].isdigit() == 0: # 去掉首尾非数字的项(非法项) 52 # print('非商品编号或非正常商品数量,已自动删除') 53 customer_choice_list.remove(element) 54 elif int(element.split(':')[0]) not in range(1, len(goods) + 1): # print('选择的商品编号不存在,已自动删除.') 55 customer_choice_list.remove(element) 56 elif int(element.split(':')[-1]) > goods[int(element.split(':')[0]) - 1]['allowance']: 57 customer_choice_list.remove(element) 58 element = element.split(':')[0] + ':' + str(goods[int(element.split(':')[0]) - 1]['allowance']) 59 print(">>>%s<<<选择了过多的数量,已自动修改为最大库存量>>%d<<" % ( 60 goods[int(element.split(':')[0]) - 1]['name'], goods[int(element.split(':')[0]) - 1]['allowance'])) 61 customer_choice_list.append(element) 62 del temp_list # 释放临时列表内存 63 print('您选择了如下商品:⤵⤵⤵⤵') # 只是展示给用户知道他买了什么 64 selected_goods = [] # 只是展示给用户知道他买了什么 65 for selection in customer_choice_list: 66 shopping_cart = {'商品名': goods[int(selection.split(':')[0]) - 1]['name'], 67 '单价': goods[int(selection.split(':')[0]) - 1]['price'], 68 '购买数量': int(selection.split(':')[-1])} 69 shopping_cart['所需金额'] = shopping_cart['单价'] * shopping_cart['购买数量'] 70 selected_goods.append(shopping_cart) 71 for selected_good in selected_goods: 72 print(selected_good) # 只是展示给用户,并没有他意 73 sum_price = 0 74 temp_list = goods.copy() # 浅拷贝商品列表,以便在删除某商品时仍可计算客户所花总价 75 for customer_choice_list_element in customer_choice_list: 76 goods[int(customer_choice_list_element.split(':')[0]) - 1]['allowance'] -= int( 77 customer_choice_list_element.split(':')[-1]) 78 if goods[int(customer_choice_list_element.split(':')[0]) - 1]['allowance'] == 0: 79 goods.pop(int(customer_choice_list_element.split(':')[0]) - 1) 80 sum_price += temp_list[int(customer_choice_list_element.split(':')[0]) - 1]['price'] * int( 81 customer_choice_list_element.split(':')[-1]) 82 wallet_allowance = wallet - sum_price 83 del temp_list # 释放临时内存 84 if wallet_allowance < 0: 85 print('余额不足,还需补充%d元.请下次多带点钱来,穷逼!' % abs(wallet_allowance)) 86 elif wallet_allowance < min(price_list): 87 print('此次购物花费%d元,余额%d元' % (sum_price, wallet_allowance)) 88 print('余额暂不够买任何商品了,下次请多带点钱来吧!') 89 else: 90 print('此次购物花费%d元,余额%d元' % (sum_price, wallet_allowance)) 91 while 'Query_Go_On_Shopping?': 92 try: 93 customer_selection = input('是否需要继续购买?Y/N').strip().lower() 94 if customer_selection == 'n': 95 shopping_count += 1 96 print('谢谢%d次惠顾,欢迎下次光临...' % shopping_count) 97 break 98 elif customer_selection == 'y': 99 show_goods() # 展示商品余量 100 shopping_count += 1 101 select_goods(wallet_allowance, shopping_count) 102 break 103 else: 104 print('选择无效,请重新选择') 105 except KeyboardInterrupt: 106 print('手动打断购物进程,再见') 107 108 109 if __name__ == '__main__': 110 show_goods() 111 select_goods(show_wallet())
不会实现的功能是:用户在购买结束后不会询问用户是否继续购买(因代码里已实现多次购买功能)
代码里用到的方法:
1️⃣print()里的占位符,使用{0}{1}...方式占位
1 def show_goods(): 2 print('**********商品列表**********') 3 print('编号\t\t商品\t\t价格\t\t库存') 4 for good_index in range(0, len(goods)): 5 good_index += 1 6 print('{0}\t\t{1}\t\t{2}\t\t{3}'.format(good_index, goods[good_index - 1]['name'], 7 goods[good_index - 1]['price'], 8 goods[good_index - 1]['allowance']))
2️⃣判断用户输入的内容的数据类型(是否为数字)
1 def show_wallet(): 2 wallet = input('偷偷show一下钱包金额:').strip() 3 if wallet.isdigit(): 4 wallet = int(wallet) 5 if wallet < min(price_list): 6 print('穷逼滚,再给你一次机会') 7 show_wallet() 8 else: 9 print('总资产%d元,开始购物吧高富帅' % wallet) 10 return wallet 11 else: 12 print('糊弄谁呢?再给你一次机会') 13 show_wallet()
3️⃣去除列表里的元素时: 单纯用while可能会删不干净
用for遍历则绝对会出错,因为在遍历列表(或字典)时不可修改其内容,不然其长度会改变,遍历一定是不成功的
可以试试浅拷贝一份列表,for遍历拷贝后的列表,在for循环里删除原列表中想要删除的元素,然后del浅拷贝的列表以释放内存
1 # 接上文 2 # 因if判断条件中变量命名写得有点长,所以没使用and连接,而是直接多个elif判断 3 customer_choice = input("请选择商品编号及数量(以':'区分),使用空格隔开: ") 4 # 如输入内容为:' 4:3:4 3:2 5:1 a:1 %:# # @ 1:120 2:m '' 5 customer_choice_list = customer_choice.split(' ') 6 print(customer_choice_list) 7 temp_list = customer_choice_list.copy() # 浅拷贝,以便后面遍历时删除无效项或非法项 8 for element in temp_list: 9 if element == '' or element == ' ': # 去空(无效项) 10 # print('过多的空格已被自动删除') 11 customer_choice_list.remove(element) 12 elif ':' not in element: # 去掉无":"匹配的项(无效项) 13 # print('无效的匹配项已被自动删除') 14 customer_choice_list.remove(element) 15 elif len(element.split(':')) != 2: # 去掉":"匹配后长度不为2(不是正常匹配)的项目(非法项) 16 # print('非法项已被自动删除') 17 customer_choice_list.remove(element) 18 elif element.split(':')[0].isdigit() == 0 or element.split(':')[-1].isdigit() == 0: # 去掉首尾非数字的项(非法项) 19 # print('非商品编号或非正常商品数量,已自动删除') 20 customer_choice_list.remove(element) 21 elif int(element.split(':')[0]) not in range(1, len(goods) + 1): # print('选择的商品编号不存在,已自动删除.') 22 customer_choice_list.remove(element) 23 elif int(element.split(':')[-1]) > goods[int(element.split(':')[0]) - 1]['allowance']: 24 customer_choice_list.remove(element) 25 element = element.split(':')[0] + ':' + str(goods[int(element.split(':')[0]) - 1]['allowance']) 26 print(">>>%s<<<选择了过多的数量,已自动修改为最大库存量>>%d<<" % ( 27 goods[int(element.split(':')[0]) - 1]['name'], goods[int(element.split(':')[0]) - 1]['allowance'])) 28 customer_choice_list.append(element) 29 del temp_list # 释放临时列表内存
然后就是for遍历上述代码返回的customer_choice_list,将与之对应的商品信息添加到购物列表里(这一步只是为了展示给用户知道他买了什么东西)
注意: 如果需要让用户可以多次购物,那么他的多次购物的代码一定要写在一个函数里
不然结算sum_price时就无法得到钱包余额,或需要重新调用结算函数,导致用户还需要重新走一次购买流程