python以ATM+购物车剖析一个项目的由来及流程
ATM+购物车
一个项目是如何从无到有的
''' 项目的由来,几个阶段 0.采集项目需求 1.需求分析 2.程序的架构设计 3.分任务开发 4.测试 5.上线运行 '''
需求分析: # 对项目需求进行分析,并提取出相应的功能

''' - 额度 15000或自定义 --> 注册功能 - 实现购物商城,买东西加入购物车,调用信用卡接口结账 --> 购物车,支付(结账)功能 - 可以提现,手续费5% --> 提现 - 支持多账户登录 --> 登录 - 支持账户间转账 --> 转账 - 记录每月日常消费流水 --> 记录流水 - 提供还款接口 --> 还款 - ATM记录操作日志 --> 日志功能 - 提供管理接口,包括添加账户、用户额度,冻结账户等... --> 管理员功能 - 用户认证功能 --> 登录认证(装饰器) '''
程序架构设计

''' 用户功能层: 负责接收用户输入的内容,并返回结果给用户(还可以做一些小的判断) 接口层: 处理业务逻辑 数据处理层: 增、删、改、查 三层架构的好处: 代码结构清晰,一层是一层的 低耦合,可扩展性强 部分之间联系不是特别固定,好扩展 比如用户层我不用cmd了,改用网页,改用APP,接口层级数据处理层不需要改动直接就可以用了 易维护、管理 出现bug比较好定位,要修改配置也比较方便,扩展功能也是,可以很快定位到目标代码,不用很长的代码翻来翻去 '''
分任务开发

''' - CTO 首席技术官 - 技术总监 - 架构师 - 项目经理 - 普通开发 UI:用户界面设计师 前段:网页的开发 后端:写业务逻辑、接口的 测试:测试软件 运维:项目部署上线 '''
测试

''' - 手动测试 传统人工去手动测试 - 自动化测试 通过脚本模拟人的行为,自动化执行测试 - 黑盒测试: 对用户界面进行测试 - 白盒测试: 对软件的性能进行测试,例如每分钟能接收多少并发量 '''
上线运行: # 将项目交给运维人员上线
部分流程具体案例
功能需求
''' - 额度15000 ---> 注册功能 - 可以提现,手续费5% ---> 提现 - 支持账户间转账 ---> 转账 - 记录消费流水 ---> 记录流水 - 提供还款接口 ---> 还款 - 用户认证功能 ---> 登陆认证,使用装饰器 '''
本文程序功能
目录规范及三层架构
各文件代码

import os import sys BASE_DIR = os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASE_DIR) from core import src if __name__ == '__main__': src.run()

from interface import user_interface from lib import common from interface import bank_interface def register(): while True: username = input("请输入用户名>>>:").strip() if username == 'q': break if user_interface.check_user_exits(username): print("用户名已存在,请重新输入") continue pwd = input("请输入密码>>>:").strip() repwd = input("请再次输入密码>>>:").strip() if pwd != repwd: print("两次密码不一致,请重新输入") continue if user_interface.register(username, pwd): print(f"{username}用户注册成功") break def login(): while True: username = input("请输入用户名>>>:").strip() if username == 'q': return False flag = user_interface.check_user_exits(username) if not flag: print(f"用户{username}不存在,请重试") continue pwd = input("请输入密码>>>:").strip() flag = user_interface.login(username, pwd) if not flag: print("密码不正确,请重试") continue print(f"{username}您好,欢迎登录!") break @common.login_auth def check_balance(): username = current_user_dict.get('username') balance = user_interface.get_balance(username) print(f"{username}您好,您的账户余额为{balance}元") @common.login_auth def repay(): while True: username = current_user_dict.get('username') money = input("请输入还款金额>>>:").strip() if not money.isdigit(): print("请正确输入金额!") continue money = int(money) flag = bank_interface.repay(username, money) if flag: print(f"{username}您好,您已成功还款{money}元") break else: print("还款失败,请您重试") @common.login_auth def withdraw(): while True: username = current_user_dict.get('username') money = input("请输入提现金额>>>:").strip() if not money.isdigit(): print("请正确输入金额!") continue money = int(money) flag = bank_interface.withdraw(username, money) if flag: print(f"{username}您好,您已成功提现{money}元,手续费{money*0.05}元,现余额为{current_user_dict['balance']}元") break else: print("还款失败,请您重试") pass @common.login_auth def transfer(): while True: username = current_user_dict.get('username') target_user = input("请输入转账收款人>>>:").strip() if target_user == 'q': break if target_user == username: continue flag = user_interface.check_user_exits(target_user) if not flag: print(f"{target_user}用户不存在,请重试") continue money = input("请输入转账金额>>>:").strip() if not money.isdigit(): print("请正确输入金额!") continue money = int(money) if money <= current_user_dict['balance']: flag = bank_interface.transfer(username, target_user, money) if flag: print(f"您已成功向{target_user}转账{money}元,现余额为{current_user_dict['balance']}元") break print("转账失败,请重试") else: print("转账失败,转账金额大于您的余额") @common.login_auth def check_flow(): username = current_user_dict.get('username') flow = user_interface.check_flow(username) print(f"{username}您好,您的个人流水如下:") for i in flow: print(i) @common.login_auth def logout(): flag = user_interface.logout() if flag: print(f"用户注销登录成功,欢迎下次光临") func_list = { "1": register, "2": login, "3": check_balance, "4": repay, "5": withdraw, "6": transfer, "7": logout, "8": check_flow } current_user_dict = { "username": None, "pwd": None, 'balance': None, 'flow': [], 'shop_cart': {}, 'lock': None, } def run(): while True: print(""" 1.注册 2.登录 3.查看余额 4.还款 5.提现 6.转账 7.注销登录 8.检查流水 """) choice = input("请输入功能编号(Q退出)>>>:").strip() if choice == 'q': print("感谢您的使用,祝您生活越快~") break elif choice in func_list: func_list[choice]() else: print("您的输入有误,请重新输入!")

from db import db_handler from lib import common from core import src def check_user_exits(username): user_dict = db_handler.select(username) if not user_dict: return False return True def register(username, pwd, balance=15000): pwd = common.get_md5(pwd) user_dict = { "username": username, "pwd": pwd, 'balance': balance, 'flow': [], 'shop_cart': {}, 'lock': False, } return db_handler.save(user_dict) def login(username: str, pwd: str): user_dict = db_handler.select(username) pwd = common.get_md5(pwd) if not user_dict: return False if user_dict['pwd'] != pwd: return False src.current_user_dict = user_dict return True def get_balance(username: str) -> float: user_dict = db_handler.select(username) src.current_user_dict['balance'] = user_dict['balance'] return user_dict.get('balance') def check_flow(username): user_dict = db_handler.select(username) return user_dict['flow'] def logout(): src.current_user_dict = { "username": None, "pwd": None, 'balance': None, 'flow': [], 'shop_cart': {}, 'lock': None, } return True

from db import db_handler from core import src def repay(username, money) -> bool: user_dict = db_handler.select(username) user_dict['balance'] += money user_dict['flow'].append(f"{username}成功还款{money}元,现余额为{user_dict.get('balance')}") src.current_user_dict = user_dict return db_handler.save(user_dict) def withdraw(username, money): user_dict = db_handler.select(username) if user_dict['balance'] >= money*1.05: user_dict['balance'] -= money*1.05 user_dict['flow'].append(f"{username}提现{money}元,手续费{money*0.05}元,现余额为{user_dict['balance']}元") src.current_user_dict = user_dict return db_handler.save(user_dict) else: return False def transfer(username, targer_user, money): user_dict = db_handler.select(username) user_dict['balance'] -= money user_dict['flow'].append(f"{username}向{targer_user}转账{money}元,现余额为{user_dict['balance']}元") src.current_user_dict = user_dict if not db_handler.save(user_dict): return False targer_user_dict = db_handler.select(targer_user) targer_user_dict['balance'] += money targer_user_dict['flow'].append(f"{targer_user}接收到{username}转账{money}元,现余额为{targer_user_dict['balance']}元") if not db_handler.save(targer_user_dict): # 这里存储失败了,那么转账人(username)的扣款操作应该要退回 return False return True

import os from conf import settings import json DB_DIR = os.path.join(settings.BASE_DIR, "db") def select(username: str): user_file_path = os.path.join(DB_DIR, f"{username}.json") if not os.path.exists(user_file_path): return False with open(user_file_path, 'r', encoding='utf-8') as f: user_dict = json.load(f) return user_dict def save(user_dict: dict) -> bool: user_file_path = os.path.join(DB_DIR, f"{user_dict['username']}.json") with open(user_file_path, 'w', encoding='utf-8') as f: json.dump(user_dict, f) return True

import hashlib from core import src def get_md5(string: str) -> str: md = hashlib.md5() md.update('md5_salt'.encode('utf-8')) md.update(string.encode('utf-8')) return md.hexdigest() def login_auth(func): def inner(*args, **kwargs): if not src.current_user_dict.get('username'): print("请先登录后再操作!") else: res = func(*args, **kwargs) return res return inner

import os import sys BASE_DIR = os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASE_DIR)
今日小错误
找了半天才发现问题,记住报错,下次看到类似报错就可以立马发现问题了

file_path = r'E:\PyCharm 2019.1.3\ATM+SHOP2\lib\common.py' # with open(file_path, 'r', 'utf-8') as f: # 报错(不要忘了写 encoding!) # print('hello') # Traceback (most recent call last): # File "E:/PyCharm 2019.1.3/ATM+SHOP2/test.py", line 2, in <module> # with open(file_path, 'r', 'utf-8') as f: # TypeError: an integer is required (got type str) with open(file_path, 'r', encoding='utf-8') as f: print('hello') # hello
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构