python-十九课 购物车

import os
import json
import time

base_dir = os.path.dirname(os.path.dirname(__file__))  # dirname获取当前文件所在的目录路径,嵌套使用就是获取上一级的路径
db_dir = os.path.join(base_dir, 'db')  # 项目根目录路径与'db'拼接
if not os.path.isdir(db_dir):  # 判断db文件目录是否存在,就是判断db文件夹存不存在
    os.mkdir(db_dir)  # 不存在就创建一个


is_login = {'status': False,'real_name': ''}  # 全局标志位记录用户状态与信息给装饰器与被装饰的函数使用

# 装饰器
def login_auth(func):
    def inner(*args, **kwargs):
        if is_login.get('status'):  # 如果有登录状态了就直接运行被装饰函数
            start_time = time.time()  # 获取时间戳
            res = func(*args, **kwargs)
            end_time = time.time()  # 再获取时间戳
            use_time = end_time - start_time
            print(f'程序执行时间为{use_time}')  # 打印统计时间
            return res
        else:       # 否则转登录去
            print('您还没有登录,请先登录')
            login()
    return inner

def register():  # 先写注册功能
    while True:
        username = input('请输入用户名q>>:').strip()
        if username == 'q':
            break
        user_file_path = os.path.join(db_dir, f'{username}.json')  # 将db文件路径与用户名.json文件名拼接,形成字符串,后续打开不需要r''了
        if os.path.isfile(user_file_path):  # 判断拼接的路径是否已经存在
            print('该用户名已经存在,请重新注册')
            continue
        password = input('请输入密码>>:').strip()  # 获取用户密码
        age = input('请输入年龄>>:').strip()  # 获取用户年龄
        user_dict = {
            'real_name': username,  # 构建用户字典
            'real_pwd': password,
            'real_age': age,
            'real_account': 85000,
            'shop_car': {}
        }
        with open(user_file_path, 'w', encoding='utf8')as f:  # 用w模式打开该文件,如果这个文件不存在,就会自动创建该文件了
            json.dump(user_dict, f)  # 先将字典转为json格式,再写入文件
            print(f'用户{username}注册成功')
            break



def login():  # 再写登录功能
    while True:
        username = input('请输入用户名q>>:').strip()
        if username == 'q':
            break
        user_file_path = os.path.join(db_dir, f'{username}.json')  # 还是先拼接出用户名文件路径
        if not os.path.isfile(user_file_path):  # 判断这个路径存不存在
            print('该用户名不存在')
            continue
        password = input('请输入密码>>:').strip()
        with open(user_file_path, 'r', encoding='utf8')as f:  # r模式打开用户文件
            user_dict2 = json.load(f)  # 先读出来,再反序列化将json格式数据转为正常格式数据
            if user_dict2.get('real_pwd') == password:  # 判断密码是否正确
                print('登录成功')
                is_login['status'] = True   # 登录上立马全局记录登录状态
                is_login['real_name'] = username  # 全局记录用户名
                break
            else:
                print('密码错误')


@login_auth
def check1():  # 再写查看功能
    while True:
        username = input('请输入用户名(q)>>:').strip()
        user_file_path = os.path.join(db_dir, f'{username}.json')  # 还是先拼接出用户名文件路径
        if username == 'q':
            break
        with open(user_file_path, 'r', encoding='utf8') as f:     # 打开用户文件字典
            user_dict = json.load(f)           # 读出后反序列化转为正常字典,再取出字典里面值,格式化打印输出
            print(f"""
            ------------user_info----------
            姓名:{user_dict.get('real_name')}
            年龄:{user_dict.get('real_age')}
            账户余额:{user_dict.get('real_account')}
            -------------------------------
            """)



#  用户可以反复添加商品,在购物车中记录数量
#  shop_car里面的数据 {'极品木瓜':[个数,单价],'印度飞饼':[个数,单价]}
@login_auth
def add_shop_car():
    temp_shop_car888 = {}    # 9.构建一个临时购物车,用户可能会反复使用购物车功能,所以必须要有一个临时购物车来反复记录用户添加商品信息,最后一次性导入导用户文件里面的shop_car里面去。
    while True:
        good_list = [['挂壁面', 3], ['印度飞饼', 22], ['极品木瓜', 666],
                     ['土耳其土豆', 999], ['伊拉克拌面', 1000],
                     ['董卓戏张飞公仔', 2000], ['仿真玩偶', 10000]
                     ]            # 1.获取商品信息(目前是写死的 后期可以动态获取)
        # print("""
        # 0.挂壁面         单价:3元
        # 1.印度飞饼       单价:22元
        # 2.极品木瓜       单价:666元
        # 3.土耳其土豆     单价:999元
        # 4.伊拉克拌面     单价:1000元
        # 5.董卓戏张飞公仔  单价:2000元
        # 6.仿真玩偶       单价:10000元
        # """)     这种手写的肯定不方便,肯定是要考虑如何实现自动化打印出所有的商品信息!!!
        for i, j in enumerate(good_list):                 # 2.循环打印商品信息供用户选择
            print(f"商品编号:{i}  |  名称:{j[0]}  |  单价:{j[1]}")
        good_id = input('请输入需要的商品编号(q)>>:').strip()   # 3.获取用户输入的商品编号

# 分隔一下  第三部分
        if good_id == 'q':         # 13.添加结束标志 用于保存购物车数据 
            user_file_path = os.path.join(db_dir, f'{is_login.get("real_name")}.json')  # 14.获取当前登录用户的字典数据文件路径
            with open(user_file_path, 'r', encoding='utf8') as f:  # 15.打开用户文件
                user_date_dict111 = json.load(f)                    # 16.读出来并反序列化为用户字典
            old_shop_car222 = user_date_dict111.get('shop_car')  # 17. 得到用户字典里面的原来的'shop_car'信息   {'印度飞饼':[10, 22]}
            
            """
            user_dict['shop_car'] = temp_shop_car 不能直接替换 可能有原先的数据
            比如(老字典)原来购物车user_dict['shop_car']里面的历史数据如下:
            {"username": "jason", "password": "123", "balance": 15000, "shop_car": {'印度飞饼':[10, 22]}}
            现在临时购物车temp_shop_car里面的信息如下
            {'印度飞饼': [1888, 22], '极品木瓜': [10, 666]}
            这个时候用上面代码又会直接把原来的{'印度飞饼':[10, 22]}数据直接覆盖掉了!!!!!!!!!
            购物车就这个地方绕,其他的地方都简单!!!!!!!!!
            """
			# 18.准备把临时购物车数据导入到用户字典里面的shop_car老购物里
            for i_name, j_list in temp_shop_car888.items():  # 19.每一次for循环拿到临时购物车里面的一组键值对!!! for循环拿出刚刚用户选购生成的临时购物车里的数据
                if i_name in old_shop_car222:       # 20. 如果临时字典里面的for循环出的键也就是商品名在老字典里面,说原购物车里面已经添加过该商品的数量。
                    old_shop_car222[i_name][0] += j_list[0]  # 21. 将老字典里面的该商品数量,增加一个临时字典里面该商品的数量!!关键!!
                else:
                    old_shop_car222[i_name] = j_list   # 22. 如果临时字典里面的for循环出的键也就是商品名不在老字典里面,说明以前没添加过,就直接将临时字典for循环出的商品名与列表作为键值对添加到老字典里面去!!!
                    # for循环玩,把老字典里面的信息都更新一遍后,准备把老字典再写进用户文件里面去!!!
            user_date_dict111['shop_car'] = old_shop_car222   # 23. 最后将用户字典里的shop_car再更新一下
            with open(user_file_path, 'w', encoding='utf8') as f1:   # 24. 再重新打开用户文键
                json.dump(user_date_dict111, f1, ensure_ascii=False)         # 25. w模式重新写入,覆盖掉原数据
            print('添加商品成功 欢迎下次再来')
            break                                         # 26. 最后结束循环

# 分隔一下   第二部分
        if not good_id.isdigit():               # 4.判断输入商品编号是否为纯数字
            print('商品编号必须是纯数字')
            continue
        good_id = int(good_id)                  # 5.把字符串转为整型数字
        if good_id not in range(len(good_list)):         # 6.判断输入的商品编号在不在超出商品的列表范围
            print('您选择的商品编号不在已存在的商品编号内 无法选择购买')
            continue
        good_list_temp = good_list[good_id]         # 7.根据商品编号获取商品信息 大列表中对的小列表
        good_name = good_list_temp[0]      # 拿到小列表中的商品名
        good_price = good_list_temp[1]     # 拿到小列表里面的商品价格
        good_num = input(f'请输入你要购买的{good_name}商品的数量>>:').strip()   # 8.获取想要购买的商品个数
        if not good_num.isdigit():
            print('商品数量必须是纯数字')
            continue
        good_num = int(good_num)                # 10.把字符串转为数字,下面就是购物车最关键的地方了!!!
        if good_name in temp_shop_car888:     # 11.如果选购的商品名已经再购物车了,说明以前已经选过了,现在又要增加数量!!
            temp_shop_car888.get(good_name)[0] += good_num  # 12.如果在里面,则要在原来该商品的数量上再加上本次输入的商品数量
        else:
            temp_shop_car888[good_name] = [good_num, good_price]  # 如果不在里面,就直接往字典里面添加键值对

            # 列表[0]可以就看成是一个变量名绑定了索引0对应的数据,现在将该变量名重新绑定给,原索引0对应的数据再加上本次用户输入的数量和了,比如
            # l1=[11,22]
            # l1[0]=l1[0]+3
            # print(l1[0])   结果就是14了
            # 也就是说,判断键是否已存在, 如果存在, 则会去该列表,将原临时购物车中的商品的数量,自增用户输入的数量
        """
        如果不判断直接添加键值对到临时字典里就会,直接把之前购物车里面的同样商品的价格数量的列表覆盖掉
        temp_shop_car888[good_name] = [goods_num,goods_price]
        # old_temp_shop_car = {'印度飞饼':[10, 22]}    用户第一次选了10个飞饼
        # new_temp_shop_car = {'印度飞饼':[10, 22] }   用户第二次右选了10个飞饼,按理说数量应该为20.但由于是直接往字典里加的,
        # 字典的键存在会替换值,所以代码直接这样就有问题了!!!
        """
@login_auth
def pay_shop_car():
    user_file_path = os.path.join(db_dir, f'{is_login["real_name"]}.json')
    with open(user_file_path, 'r', encoding='utf8')as f:
        user_dict5 = json.load(f)
        user_shop_car = user_dict5.get('shop_car')
        if not user_shop_car:
            print('购物车为空,请选购商品!!')
            return
        current_balance = user_dict5.get('balance')
        total_money = 0
        for i in user_shop_car.values():
            total_money += i[0] * i[1]  # 统计总价是一个for循环一次,自增一次的过程
        if total_money > current_balance:
            print('您的余额不够')
            return
        user_dict5['balance'] -= total_money  # 在原有的余额基础上减掉总价钱
        user_dict5['shop_car'] = {}  # 扣完钱后,清空购物车原数据!!!
        with open(user_file_path, 'w', encoding='utf8')as f1:
            json.dump(user_dict5, f1)
            print(f"您本次消费{total_money},卡上余额{user_dict5['balance']}")

上周内容回顾

  • os模块

    主要与操作系统打交道
        os.mkdir()			创建单级目录
        os.makedirs()		创建多级目录(包含单级)
        os.rmdir()			删除单级目录(空)
        os.removedirs()     删除多级目录(空)
        os.listdir()		查看指定路径下的内容名称
        os.rename()			重命名文件
        os.remove()			删除文件
        os.path.exists()	判断路径是否存在
        os.path.isdir()		判断路径是否是目录
        os.path.isfile()    判断路径是否是文件
        os.path.join()		 拼接路径
        os.path.dirname()    获取执行文件所在的目录路径
        os.path.getsize()	 获取文件大小(字节)
        os.getcwd()			获取当前工作目录
        os.chdir()			切换工作目录
    
  • sys模块

    主要与python解释器打交道
        sys.path
        sys.getrecursionlimit
        sys.setrecurionlimit
        sys.version
        sys.argv
    
  • json模块

    序列化模块
    	序列化
        	将数据类型转换成json格式字符串
    	反序列化
        	将json格式字符串转成数据类型
       
    json格式字符串
    	双引号
     
    具体操作方法
        dump()
        dumps()
        load()
        loads()
        
    ps:涉及到不同语言之间数据交互 大概率是用字典
    	{"name":"jason","pwd":123}
    
  • 模块实战演练

    注册功能
    登录功能
    

今日内容概要

  • json模块补充说明

  • 作业讲解

    思路非常的重要!!!
    

今日内容详细

json模块补充说明

import json

d = {'name': 'jason老师', 'pwd': 123}
res = json.dumps(d)  # 针对中文会自动转码  我们在查看的时候不方便
print(res)
# res = json.dumps(d, ensure_ascii=False)
# print(res)

作业讲解

1.编写一个统计指定文件类型的脚本工具
 输入指定类型的文件后缀
     eg:.txt
 并给出一个具体路径 之后统计该类型文件在该文件下的个数
  ps:简单实现即可 无需优化
import os

# 1.获取目录路径
dir_path = input('请输入目录路径>>>:').strip()  # aaa
# 2.获取指定后缀名
ends_name = input('请输入想要统计的文件后缀名>>>:').strip()  # .txt
# 3.列举目录路径下所有内容的名称
path_list = os.listdir(dir_path)  # ['a.txt', 'a1', 'a2', 'b.txt', 'c.txt', 'd.py', 'e.py']
# 4.循环获取每一个内容名称 判断是否以用户指定的文件后缀名结尾
file_num = 0
for name in path_list:
    if name.endswith(ends_name):
        file_num += 1
print(f'在{dir_path}目录第一层级 以后缀名{ends_name}结尾的文件个数有:{file_num}')
"""
1.如果出现了目录的嵌套 如何统计
    请说出大致思路  课下不用编写代码
2.只给一个目录的路径 直接统计该目录下第一层所有类型的内容数量
    .txt:3 .py:2 目录:2 课下尝试编写代码
"""     
2.针对json实操 尝试单文件多用户(一行一个)是否可实现>>>:哪个更方便
    不要求完成 单纯体会两种思路的难易
3.编程小练习
 有一个目录文件下面有一堆文本文件
     eg:
      db目录
            J老师视频合集
            R老师视频合集
            C老师视频合集
            B老师视频合集
 文件内容自定义即可 要求循环打印出db目录下所有的文件名称让用户选择
  用户选择哪个文件就自动打开该文件并展示内容
  涉及到文件路径全部使用代码自动生成 不准直接拷贝当前计算机固定路径
import os

# 1.获取执行文件所在的路径
base_dir = os.path.dirname(__file__)  # D:/pythonProject03/day20
# 2.拼接存储文本文件的目录路径
data_dir = os.path.join(base_dir, 'data')  # D:/pythonProject03/day20/data
# 3.列举目录下所有内容名称
file_name_list = os.listdir(data_dir)  # ['B老师视频合集.txt', 'J老师视频合集.txt', 'K老师视频合集.txt', 'R老师视频合集.txt', 'Z老师视频合集.txt']
while True:  # 添加循环让项目更加的合理
    # 4.循环打印文件名供用户选择查看
    for num, file_name in enumerate(file_name_list, start=1):  # 枚举 主要用于给数据添加编号便于查看和选取
        print(num, file_name)
    # 5.等待for循环展示完毕之后 获取用户想要查看的编号
    choice_num = input('请输入您想要查看的文件编号(q)>>>:').strip()  # 获取到的用户输入是字符串 而列表索引取值需要用数字
    if choice_num == 'q':
        print('拜拜 下次再见 等你哟~')
        break
    # 6.判断用户输入是否是纯数字
    if not choice_num.isdigit():
        print('你眼瞎啊 编号只能是数字 你妹的!')
        continue
    choice_num = int(choice_num)  # 100
    # 7.判断数字是否在列表的索引范围内
    if choice_num not in range(1, len(file_name_list) + 1):  # range(1, 6)
        print('我看你是真瞎 编号不在范围内 看清楚好好输')
        continue
    # 8.索引取值获取用户想要查看的文件名称
    target_name = file_name_list[choice_num - 1]  # 'B老师视频合集.txt'
    # 9.拼接文件的绝对路径(因为站在执行文件的角度找不到文本文件)
    target_file_path = os.path.join(data_dir, target_name)
    # 10.利用文件操作打开文件并读取内容
    with open(target_file_path, 'r', encoding='utf8') as f:
        for line in f:
            print(line, end='')
    print()
    print('-------------------本次观看完了哟!----------------------')


4.周末大作业(尝试编写)
 # 项目功能
    1.用户注册
     2.用户登录
     3.添加购物车
     4.结算购物车
 # 项目说明
    用户数据采用json格式存储到文件目录db下 一个用户一个单独的文件
     数据格式 {"name":"jason","pwd":123} 
         # ps:文件名可以直接用用户名便于校验
     用户注册时给每个用户添加两个默认的键值对(账户余额 购物车)
      {"balance":15000,"shop_car":{}}
     添加购物车功能 商品列表可以自定义或者采用下列格式
            good_list = [
                    ['挂壁面',3]
                    ['印度飞饼', 22]
                 ['极品木瓜', 666], 
                 ['土耳其土豆', 999],  
                 ['伊拉克拌面', 1000],  
                 ['董卓戏张飞公仔', 2000],  
                 ['仿真玩偶', 10000] 
            ]
      用户可以反复添加商品,在购物车中记录数量
        {'极品木瓜':[个数,单价]}
     结算购物车
      获取用户购物车中所有的商品计算总价并结算即可
  针对添加购物车和结算只有登录的用户才可以执行

购物车项目

1.单个py文件采用函数版本先写 后期如果有需要再拆分成目录规范
2.先搭建项目框架
	空函数 功能字典 while循环匹配
3.注册功能
4.登录功能
5.添加购物车和结算购物车都必须要求用户登录才可以执行
	校验用户是否登录装饰器
6.添加购物车
	一定要注意购物车字典里面是否已经有历史数据 
7.结算购物车

作业

1.练习今日购物车 务必滚瓜烂熟
-----------------------------------------------------------------------
2.学有余力的尝试扩展新功能
	账户充值、查看购物车、记录消费流水、清空购物车、编辑购物车、转账功能
3.尝试着拆分成软件开发目录规范
posted @   tengyifan  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示