如何实现可调用带属性类的菜单并将数据保存至CSV?
问题修复与最简实现方案
原代码核心问题
- 类定义顺序错误:
User类在Logistics_System实例化后才定义,导致调用时找不到类 - 继承关系混乱:
User无需继承物流系统类,应作为独立实体存在 - 方法定义缺陷:
user_input缺少实例/类参数,未定义的变量直接使用 - 缺失CSV持久化逻辑:没有实现数据的读写存储
- 菜单逻辑不合理:除选项1外直接退出,递归调用菜单易引发栈溢出
最简实现代码
import csv from typing import List # 1. 定义用户实体类 class User: def __init__(self, first_name: str, last_name: str, user_id: str, address: str, phone: int, password: str): self.first_name = first_name self.last_name = last_name self.email = f"{first_name.lower()}.{last_name.lower()}@expressdelivery.com" self.user_id = user_id self.address = address self.phone = phone self.password = password # 转换为CSV行数据 def to_csv_row(self) -> list: return [self.first_name, self.last_name, self.email, self.user_id, self.address, self.phone, self.password] # 从CSV行数据创建User实例 @classmethod def from_csv_row(cls, row: list) -> 'User': return cls( first_name=row[0], last_name=row[1], user_id=row[3], address=row[4], phone=int(row[5]), password=row[6] ) # 2. 定义物流系统核心类,负责菜单与数据操作 class LogisticsSystem: def __init__(self, csv_path: str = "users.csv"): self.csv_path = csv_path self.users: List[User] = self._load_users_from_csv() print("Welcome to Express Delivery") # 从CSV加载用户数据 def _load_users_from_csv(self) -> List[User]: users = [] try: with open(self.csv_path, 'r', newline='', encoding='utf-8') as f: reader = csv.reader(f) next(reader) # 跳过表头 for row in reader: users.append(User.from_csv_row(row)) except FileNotFoundError: # 文件不存在时自动创建表头 self._save_users_to_csv(users, write_header=True) return users # 保存用户数据到CSV def _save_users_to_csv(self, users: List[User], write_header: bool = False): with open(self.csv_path, 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) if write_header: writer.writerow(["First Name", "Last Name", "Email", "ID", "Address", "Phone", "Password"]) for user in users: writer.writerow(user.to_csv_row()) # 用户操作子菜单 def user_management_menu(self): while True: print("\n--- 用户管理 ---") print("[1]. 添加用户") print("[2]. 删除用户") print("[3]. 修改用户") print("[4]. 返回主菜单") try: opt = int(input("选择操作: ")) if opt == 1: self._add_user() elif opt == 2: self._remove_user() elif opt == 3: self._update_user() elif opt == 4: break else: print("无效选项,请重新输入") except ValueError: print("输入错误,请输入数字") # 添加用户 def _add_user(self): try: first = input("名字: ") last = input("姓氏: ") user_id = input("用户ID: ") address = input("地址: ") phone = int(input("手机号: ")) password = input("密码: ") new_user = User(first, last, user_id, address, phone, password) self.users.append(new_user) self._save_users_to_csv(self.users) print("用户添加成功!") except ValueError: print("手机号格式错误,必须是整数") # 删除用户 def _remove_user(self): user_id = input("输入要删除的用户ID: ") for idx, user in enumerate(self.users): if user.user_id == user_id: del self.users[idx] self._save_users_to_csv(self.users) print("用户删除成功!") return print("未找到该用户") # 修改用户 def _update_user(self): user_id = input("输入要修改的用户ID: ") for user in self.users: if user.user_id == user_id: print("留空则保持原数据") user.first_name = input(f"名字 ({user.first_name}): ") or user.first_name user.last_name = input(f"姓氏 ({user.last_name}): ") or user.last_name user.address = input(f"地址 ({user.address}): ") or user.address phone_input = input(f"手机号 ({user.phone}): ") user.phone = int(phone_input) if phone_input else user.phone user.password = input(f"密码: ") or user.password user.email = f"{user.first_name.lower()}.{user.last_name.lower()}@expressdelivery.com" self._save_users_to_csv(self.users) print("用户修改成功!") return print("未找到该用户") # 主菜单 def main_menu(self): while True: print("\n--- 主菜单 ---") print("[1]. 增删改: 用户") print("[2]. 增删改: 企业客户") print("[3]. 增删改: 个人客户") print("[4]. 添加自行车到系统") print("[5]. 添加卡车到系统") print("[6]. 添加船只到系统") print("[7]. 创建货运订单") print("[8]. 向订单添加物品") print("[9]. 更新订单状态") print("[0]. 退出") try: option = int(input("选择操作: ")) if option == 1: self.user_management_menu() elif option == 0: print("程序退出") break else: print("该功能暂未实现") except ValueError: print("输入错误,请输入有效数字") # 启动系统 if __name__ == "__main__": system = LogisticsSystem() system.main_menu()
实现说明
- 实体类与CSV交互:
User类通过to_csv_row和from_csv_row方法实现对象与CSV行数据的双向转换,保证数据格式统一 - 数据持久化:
LogisticsSystem类负责加载和保存CSV数据,文件不存在时自动创建表头 - 菜单分层:主菜单调用子菜单(如用户管理),避免逻辑混乱,用循环替代递归防止栈溢出
- 增删改逻辑:所有用户操作直接修改内存中的用户列表,操作完成后立即写入CSV,保证数据一致性
- 基础错误处理:针对输入格式错误(如非整数手机号)做了校验,提升程序稳定性
你可以按照此模式扩展其他实体(如企业客户、交通工具等),只需复制User类的结构,修改属性和CSV交互方法即可。
内容的提问来源于stack exchange,提问作者Gino Chen
相关产品推荐
相关产品推荐

