基于Python面向对象的客户信息管理系统完整解析+源码
基于Python面向对象的客户信息管理系统完整解析
目录
一、项目概述
本系统采用面向对象编程思想开发,以Customer类作为核心载体,使用类静态字典存储全部客户数据,完整实现增、删、改、查四大基础业务功能,同时配套严格的数据格式校验,适配真实业务录入规范。
系统功能清单
- 添加客户:带编号唯一性、姓名非空、性别、手机号、邮箱、年龄多重校验
- 批量查看所有客户:格式化表格输出,无数据友好提示
- 根据客户编号单点查询客户详情
- 根据编号删除客户信息
- 修改客户信息:支持回车保留原有数据,修改内容复用统一校验规则
- 系统安全退出
技术亮点
- 数据校验逻辑全部封装独立函数,新增、修改功能复用同一套校验,无冗余代码
- 区分实例方法、类方法,职责清晰,符合面向对象封装规范
- 修改模块专用工具函数,解决"部分字段不修改"的业务场景
- 正则校验邮箱、规范11位手机号、4位唯一客户编号,贴近企业实际录入要求
- 界面分层打印分割线,输出美观,交互提示清晰易懂
二、整体代码结构分层
代码分为五大模块,分层解耦,便于阅读、维护、扩展:
- 依赖导入模块:导入正则库
re用于邮箱格式校验 - 核心实体类
Customer:封装客户属性、数据存储容器、所有业务操作方法(增删改查、打印) - 全局通用校验函数:编号、姓名、性别、年龄、手机号、邮箱独立校验方法
- 修改专用工具函数:
safe_modify_input,适配修改场景"可留白不修改"需求 - 系统主程序入口:菜单循环、功能调度逻辑
三、分模块代码详细讲解
(一)依赖导入
import re
作用:引入正则表达式工具,用于邮箱格式合法性校验,过滤xxx@xx.com之外的非法格式。
(二)核心实体类 Customer(系统核心)
1. 静态数据容器
class Customer:
# 静态字典:全局存储客户
customers = {}
customers是类属性(静态变量),不属于任何实例对象,所有客户实例统一存放在该字典中:
- 字典键:客户编号
cid(保证唯一,用于快速查询、删除、修改) - 字典值:
Customer类实例对象,包含该客户全部属性
优势:全局统一管理数据,不需要额外全局变量,数据内聚在类内部,符合封装思想。
2. 构造方法 init
def __init__(self, cid, name, gender, age, phone, email):
self.cid = cid
self.name = name
self.gender = gender
self.age = age
self.phone = phone
self.email = email
构造方法用于创建单个客户实例,定义客户6个核心属性:
cid:客户编号(规避python内置关键字id,避免冲突)name:客户姓名gender:性别age:年龄(数字)phone:手机号email:电子邮箱
3. 实例方法 show_single_info()
def show_single_info(self):
"""实例方法:打印单个客户详情"""
print("-" * 50)
print(f"客户编号:{self.cid}")
print(f"姓 名:{self.name}")
print(f"性 别:{self.gender}")
print(f"年 龄:{self.age}")
print(f"手 机 号:{self.phone}")
print(f"邮 箱:{self.email}")
print("-" * 50)
- 类型:实例方法,只能通过客户对象调用
- 作用:打印当前这一个客户的完整信息,分割线美化输出
- 使用场景:按编号查询客户、修改前展示原有客户信息
4. 类方法(@classmethod)统一管理全局数据
类方法使用装饰器@classmethod,第一个参数为cls,代表当前类,不需要创建实例即可调用,专门操作静态字典customers。
1. show_customer_list:打印全部客户列表
@classmethod
def show_customer_list(cls):
"""类方法:打印所有客户列表"""
if not cls.customers:
print("暂无任何客户数据")
return
print("=" * 80)
print(f"{'编号':<8}{'姓名':<10}{'性别':<6}{'年龄':<6}{'手机号':<15}{'邮箱':<25}")
print("-" * 80)
for customer in cls.customers.values():
print(f"{customer.cid:<8}{customer.name:<10}{customer.gender:<6}"
f"{customer.age:<6}{customer.phone:<15}{customer.email:<25}")
print("=" * 80)
- 判断字典长度,无数据则提示"暂无任何客户数据"
- 使用格式化对齐语法
:<8控制列宽,表格整齐,可读性强
2. get_customer_by_id:根据编号查询客户对象
@classmethod
def get_customer_by_id(cls, cid):
"""类方法:根据编号查询客户"""
return cls.customers.get(cid)
字典get方法,不存在返回None
3. add_customer:新增客户逻辑
@classmethod
def add_customer(cls, customer):
"""类方法:添加客户"""
if customer.cid in cls.customers:
print(f"客户编号 {customer.cid} 已存在,添加失败!")
return False
cls.customers[customer.cid] = customer
print(f"客户 {customer.name} 添加成功!")
return True
判断编号是否重复,重复则拦截添加
4. delete_customer_by_id:删除客户
@classmethod
def delete_customer_by_id(cls, cid):
"""类方法:删除客户"""
if cid not in cls.customers:
print(f"客户编号 {cid} 不存在,删除失败!")
return False
name = cls.customers[cid].name
del cls.customers[cid]
print(f"客户 {name} 删除成功!")
return True
先校验编号存在性,不存在给出错误提示
5. modify_customer:修改客户统一更新逻辑
@classmethod
def modify_customer(cls, cid, **kwargs):
"""类方法:修改客户信息"""
if cid not in cls.customers:
print(f"客户编号 {cid} 不存在,修改失败!")
return False
customer = cls.customers[cid]
for key, value in kwargs.items():
if hasattr(customer, key) and value is not None:
setattr(customer, key, value)
print(f"客户 {customer.name} 信息修改成功!")
return True
直接覆盖对象原有属性
(三)通用数据校验函数(复用核心)
系统新增、修改功能都需要校验数据格式,将校验逻辑单独封装为独立函数,一处编写、多处调用,减少重复代码,后续修改规则只改一处即可全局生效。
1. input_check_cid:校验4位纯数字、编号不可重复
def input_check_cid():
"""校验客户编号:4位数字且不重复"""
while True:
cid = input("请输入4位客户编号:").strip()
if not cid.isdigit() or len(cid) != 4:
print("编号格式错误:必须为4位数字")
continue
if cid in Customer.customers:
print(f"编号 {cid} 已存在,请重新输入")
continue
return cid
2. input_check_name:姓名不能为空
def input_check_name():
"""校验姓名:不能为空"""
while True:
name = input("请输入客户姓名:").strip()
if not name:
print("姓名不能为空")
continue
return name
3. input_check_gender:仅允许输入"男"/“女”
def input_check_gender():
"""校验性别:仅允许'男'或'女'"""
while True:
gender = input("请输入性别(男/女):").strip()
if gender not in ["男", "女"]:
print("性别输入错误,请输入'男'或'女'")
continue
return gender
4. input_check_age:必须是数字,年龄区间1~149
def input_check_age():
"""校验年龄:1-149之间的整数"""
while True:
age_str = input("请输入年龄:").strip()
if not age_str.isdigit():
print("年龄必须是数字")
continue
age = int(age_str)
if age < 1 or age > 149:
print("年龄必须在1-149之间")
continue
return age
5. input_check_phone:11位数字、1开头、第二位3-9
def input_check_phone():
"""校验手机号:11位数字、1开头、第二位3-9"""
while True:
phone = input("请输入11位手机号:").strip()
if not phone.isdigit() or len(phone) != 11 or phone[0] != "1" or not (3 <= int(phone[1]) <= 9):
print("手机号格式错误:11位数字、1开头、第二位3-9")
continue
return phone
循环输入,直到格式完全正确才返回结果,保证存入系统的数据全部合规。
6. input_check_email:正则匹配标准邮箱格式
def input_check_email():
"""校验邮箱:标准邮箱格式"""
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
while True:
email = input("请输入邮箱:").strip()
if not re.match(email_pattern, email):
print("邮箱格式错误,请输入有效的邮箱地址")
continue
return email
正则匹配标准邮箱格式,拦截无@、无域名的非法邮箱
(四)修改专用工具函数 safe_modify_input
设计背景
新增客户时所有字段必须完整填写,但修改场景存在特殊需求:用户只想改姓名,年龄、手机号等其他字段保持原有数据,直接回车跳过即可。
def safe_modify_input(prompt, old_val, check_func=None):
"""
修改专用输入函数:支持回车保留原值
Args:
prompt: 输入提示语
old_val: 原有值
check_func: 校验函数,None表示无需校验
Returns:
新输入值或原值
"""
while True:
user_input = input(prompt).strip()
# 直接回车,保留原值
if user_input == "":
return old_val
# 无校验直接返回输入
if check_func is None:
return user_input
# 临时替换标准输入,复用原有校验函数
import sys
from io import StringIO
sys.stdin = StringIO(user_input + "\n")
try:
res = check_func()
sys.stdin = sys.__stdin__
return res
except:
sys.stdin = sys.__stdin__
print("输入格式错误,重新输入或直接回车保留原值!")
核心逻辑:
- 用户输入为空(回车):直接返回旧值,不修改
- 用户输入内容:把输入文本模拟成控制台输入,调用统一校验函数做格式校验
- 校验失败:提示错误,循环重新输入;校验通过返回新值
实现效果:修改时和新增使用完全同一套校验标准,数据一致性强,交互更人性化。
(五)主程序入口:菜单循环调度
def main():
"""主程序入口"""
menu_tip = """
========== 客户信息管理系统 ==========
1. 添加客户
2. 查看所有客户
3. 查询客户详情
4. 删除客户
5. 修改客户信息
6. 退出系统
=====================================
"""
while True:
print(menu_tip)
choice = input("请输入功能序号(1-6):").strip()
match choice:
case "1": # 添加客户
print("\n--- 添加客户 ---")
cid = input_check_cid()
name = input_check_name()
gender = input_check_gender()
age = input_check_age()
phone = input_check_phone()
email = input_check_email()
customer = Customer(cid, name, gender, age, phone, email)
Customer.add_customer(customer)
case "2": # 查看全部
print("\n--- 客户列表 ---")
Customer.show_customer_list()
case "3": # 查询单个
print("\n--- 查询客户 ---")
cid = input("请输入要查询的客户编号:").strip()
customer = Customer.get_customer_by_id(cid)
if customer:
customer.show_single_info()
else:
print(f"未找到编号为 {cid} 的客户")
case "4": # 删除
print("\n--- 删除客户 ---")
cid = input("请输入要删除的客户编号:").strip()
Customer.delete_customer_by_id(cid)
case "5": # 修改
print("\n--- 修改客户信息 ---")
cid = input("请输入要修改的客户编号:").strip()
customer = Customer.get_customer_by_id(cid)
if not customer:
print(f"未找到编号为 {cid} 的客户")
continue
print("当前客户信息:")
customer.show_single_info()
print("\n请输入新信息(直接回车保留原值):")
# 使用safe_modify_input实现可留白修改
new_name = safe_modify_input(f"姓名(原值:{customer.name}):",
customer.name, input_check_name)
new_gender = safe_modify_input(f"性别(原值:{customer.gender}):",
customer.gender, input_check_gender)
new_age = safe_modify_input(f"年龄(原值:{customer.age}):",
customer.age, input_check_age)
new_phone = safe_modify_input(f"手机号(原值:{customer.phone}):",
customer.phone, input_check_phone)
new_email = safe_modify_input(f"邮箱(原值:{customer.email}):",
customer.email, input_check_email)
Customer.modify_customer(cid,
name=new_name,
gender=new_gender,
age=new_age,
phone=new_phone,
email=new_email)
case "6": # 退出
print("感谢使用客户信息管理系统,再见!")
break
case _: # 输入错误兜底
print("输入错误,请输入1-6之间的数字!")
if __name__ == "__main__":
main()
程序结构解析:
while True无限循环,只要不选择6就持续展示菜单match-case多分支匹配,根据用户输入数字跳转对应业务- 每个分支只做流程调度,具体录入、校验、数据操作全部调用封装好的函数/类方法,主循环代码简洁干净
case _兜底分支,处理1-6以外的非法输入,提升系统容错
四、核心业务流程演示
1. 添加客户流程
菜单选1 → 依次调用校验函数录入编号、姓名、性别、年龄、手机、邮箱 → 创建Customer实例 → 调用add_customer存入静态字典。
2. 查询客户流程
菜单选3 → 输入编号 → get_customer_by_id查找对象 → 对象存在则调用show_single_info打印详情。
3. 修改客户流程
菜单选5 → 输入编号校验是否存在 → 展示原有信息 → 循环调用safe_modify_input录入可留白新数据 → 调用modify_customer覆盖属性保存。
4. 删除客户流程
菜单选4 → 输入编号 → delete_customer_by_id校验并删除字典中对应键值对。
五、代码设计优势总结
1. 面向对象封装规范
客户数据、数据操作全部封装在Customer类,区分实例方法、类方法,数据不暴露在全局,安全性高。
2. 高复用、低冗余
所有校验逻辑封装独立函数,新增、修改共用一套规则,避免重复编写判断代码,后期维护成本极低。
3. 贴合真实业务需求
- 修改功能支持回车保留原值,符合实际业务操作习惯
- 手机号、邮箱格式严格校验,保证数据质量
- 表格化输出,界面美观易读
4. 扩展性强
- 新增客户属性只需在
Customer类中添加字段 - 新增校验规则只需在对应校验函数中修改
- 新增业务功能只需在主菜单中添加分支
5. 错误处理完善
- 输入格式错误有明确提示
- 编号重复、客户不存在等业务异常有友好提示
- 非法菜单输入有兜底处理
六、可扩展优化方向(拓展思考)
-持久化存储:将字典数据写入 txt/json 文件,程序关闭后数据不丢失;
-分页查询:客户数量过多时,分页展示列表;
-模糊搜索:根据姓名关键字批量查询客户;
-日志记录:新增、修改、删除操作记录操作日志;
-界面升级:使用 GUI 库制作可视化窗口。
七、完整代码整合
import re
# 客户信息管理系统
class Customer:
# 静态字典:全局存储客户
customers = {}
def __init__(self, cid, name, gender, age, phone = "未知", email = ""):
self.cid = cid
self.name = name
self.gender = gender
self.age = age
self.phone = phone
if phone == "":
self.phone = "未知"
else:
self.phone = phone
self.email = email
def show_single_info(self):
"""实例方法:打印单个客户详情"""
print("-" * 50)
print(f"客户编号:{self.cid}")
print(f"姓 名:{self.name}")
print(f"性 别:{self.gender}")
print(f"年 龄:{self.age}")
print(f"手 机 号:{self.phone}")
print(f"邮 箱:{self.email}")
print("-" * 50)
@classmethod
def show_customer_list(cls):
"""类方法:展示全部客户列表"""
if len(cls.customers) == 0:
print("暂无任何客户数据!")
return
print("=" * 80)
print(f"{'客户编号':<8}{'姓名':<8}{'性别':<6}{'年龄':<6}{'手机号':<15}{'邮箱'}")
print("-" * 80)
for cust in cls.customers.values():
print(f"{cust.cid:<8}{cust.name:<8}{cust.gender:<6}{cust.age:<6}{cust.phone:<15}{cust.email}")
print("=" * 80)
@classmethod
def get_customer_by_id(cls, cid):
"""根据编号查询客户对象"""
return cls.customers.get(cid)
@classmethod
def get_customer_by_name(cls, name):
"""根据姓名查询客户对象列表"""
flag = False
for cust in cls.customers.values():
if cust.name == name:
flag = True
print(f"{cust.cid:<8}{cust.name:<8}{cust.gender:<6}{cust.age:<6}{cust.phone:<15}{cust.email}")
if not flag:
print(f"未找到姓名为【{name}】的客户")
@classmethod
def add_customer(cls, customer_obj):
"""添加客户,校验编号重复"""
cid = customer_obj.cid
if cid in cls.customers:
print(f"错误:编号{cid}已存在,不能重复添加!")
return False
cls.customers[cid] = customer_obj
print(f"客户【{customer_obj.name}】添加成功!")
return True
@classmethod
def delete_customer_by_id(cls, cid):
"""根据编号删除客户"""
if cid not in cls.customers:
print(f"错误:不存在编号【{cid}】的客户!")
return False
cust = cls.customers[cid]
del cls.customers[cid]
print(f"客户【{cust.name}】删除成功!")
return True
@classmethod
def modify_customer(cls, cid, new_name, new_gender, new_age, new_phone, new_email):
"""修改客户信息统一更新方法"""
if cid not in cls.customers:
print(f"修改失败:编号【{cid}】不存在!")
return False
cust = cls.customers[cid]
cust.name = new_name
cust.gender = new_gender
cust.age = new_age
cust.phone = new_phone
cust.email = new_email
print(f"编号{cid}客户信息修改完成!")
return True
# -------------------------- 通用校验工具函数 --------------------------
def input_check_cid():
"""校验4位数字唯一客户编号"""
count = 1
while True:
cid = input("请输入客户编号(4位数字,不可重复):").strip()
count += 1
if count > 3:
print("输入错误次数过多,请重新启动程序输入!")
break
if len(cid) != 4 or not cid.isdigit():
print("输入错误!编号必须为4位纯数字。")
continue
if cid in Customer.customers:
print(f"编号{cid}已存在,请更换编号!")
continue
return cid
def input_check_name():
"""校检非空姓名(新增客户用,自带input)"""
while True:
name = input("请输入客户姓名:").strip()
if not name:
print("输入错误!姓名不能为空。")
continue
return name
def input_check_gender():
"""校验性别只能男/女(新增客户用,自带input)"""
while True:
gender = input("请输入客户性别(男/女):").strip()
if gender not in ["男", "女"]:
print("输入错误!性别仅支持 男 或 女。")
continue
return gender
def input_check_age():
"""校验合法年龄 1~149(新增客户用,自带input)"""
while True:
age_str = input("请输入客户年龄:").strip()
if not age_str.isdigit():
print("输入错误!年龄必须是数字。")
continue
age = int(age_str)
if 0 < age < 150:
return age
print("输入错误!年龄范围1~149。")
def input_check_phone():
"""校验11位合法手机号(新增客户用,自带input)"""
while True:
phone = input("请输入11位手机号:").strip()
if phone == "":
return ""
if not phone.isdigit() or len(phone) != 11 or phone[0] != "1" or not (3 <= int(phone[1]) <= 9):
print("手机号格式错误:11位数字、1开头、第二位3-9")
continue
return phone
def input_check_email():
"""简易邮箱格式校验(新增客户用,自带input)"""
pattern = r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9]+\.[a-zA-Z]+$'
while True:
email = input("请输入客户邮箱:").strip()
if email == "":
return ""
if re.match(pattern, email):
return email
print("邮箱格式不正确,请重新输入!")
# ========= 新增:纯校验逻辑(无input输入,专供修改功能使用,杜绝重复弹窗) =========
def check_only_name(val):
return len(val.strip()) > 0
def check_only_gender(val):
return val.strip() in ["男", "女"]
def check_only_age(val):
if not val.isdigit():
return False
return 1 <= int(val) <= 149
def check_only_phone(val):
if val == "":
return True
if len(val) != 11 or not val.isdigit() or val[0] != "1" or not (3 <= int(val[1]) <=9):
return False
return True
def check_only_email(val):
if val == "":
return True
pattern = r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9]+\.[a-zA-Z]+$'
return re.match(pattern, val) is not None
# ========= 修复后的修改输入函数:不再劫持stdin、不再调用带input的校验函数 =========
def safe_modify_input(prompt, old_val, check_func):
"""
修改页面通用输入封装函数
prompt:输入提示
old_val:原值(回车则保留)
check_func:纯校验函数(无input)
"""
while True:
user_input = input(prompt).strip()
# 直接回车,返回原有值,不修改
if user_input == "":
return old_val
# 校验输入合法性
if check_func(user_input):
# 年龄特殊:转数字
if check_func == check_only_age:
return int(user_input)
return user_input
# 校验失败,打印对应错误提示,循环重输
if check_func == check_only_name:
print("输入错误!姓名不能为空。")
elif check_func == check_only_gender:
print("输入错误!性别仅支持 男 或 女。")
elif check_func == check_only_age:
print("输入错误!年龄必须是1~149的数字。")
elif check_func == check_only_phone:
print("手机号格式错误:11位数字、1开头、第二位3-9,留空填未知")
elif check_func == check_only_email:
print("邮箱格式不正确,直接回车留空即可")
# 主菜单
menu_tip = """
=============================客户信息管理系统 主菜单 ================================
1. 添加客户信息
2. 查看全部客户列表
3. 查询客户信息
4. 根据编号删除客户
5. 修改客户信息
6. 退出系统
==============================================================================="""
if __name__ == "__main__":
print("========================欢迎使用客户信息管理系统!==========================")
# 初始化测试数据
c1 = Customer("1001", "张三", "男", 20, "13800138000", "172@qq.com")
c2 = Customer("1002", "李四", "女", 21, "13900139000", "173@qq.com")
c3 = Customer("1003", "王五", "男", 22, "14000140000", "174@qq.com")
Customer.add_customer(c1)
Customer.add_customer(c2)
Customer.add_customer(c3)
while True:
print(menu_tip)
choice = input("请输入功能序号(1-6):").strip()
match choice:
case "1":
print("\n-----【新增客户】-----")
cid = input_check_cid()
if cid is not None:
name = input_check_name()
gender = input_check_gender()
age = input_check_age()
phone = input_check_phone()
email = input_check_email()
new_cust = Customer(cid, name, gender, age, phone, email)
Customer.add_customer(new_cust)
case "2":
print("\n-----【全部客户列表】-----")
Customer.show_customer_list()
case "3":
print("\n-----【查询指定客户】-----")
match input("查询方式:1.编号查询 2.姓名查询\n请输入查询方式序号:").strip():
case "1":
search_id = input("请输入要查询的客户编号:").strip()
target = Customer.get_customer_by_id(search_id)
if target:
target.show_single_info()
else:
print(f"未找到编号为【{search_id}】的客户")
case "2":
search_name = input("请输入要查询的客户姓名:").strip()
Customer.get_customer_by_name(search_name)
case "4":
print("\n-----【删除客户】-----")
del_id = input("请输入要删除的客户编号:").strip()
Customer.delete_customer_by_id(del_id)
case "5":
print("\n-----【修改客户信息】-----")
edit_id = input("请输入要修改的客户编号:").strip()
edit_cust = Customer.get_customer_by_id(edit_id)
if not edit_cust:
print(f"编号{edit_id}不存在,无法修改!")
continue
print("==========================当前原有客户信息 ============================")
edit_cust.show_single_info()
print("提示:直接回车不修改当前项")
# 修改功能调用【纯校验函数】,不会重复弹出输入框
new_name = safe_modify_input("新姓名:", edit_cust.name, check_only_name)
new_gender = safe_modify_input("新性别(男/女):", edit_cust.gender, check_only_gender)
new_age = safe_modify_input("新年龄:", edit_cust.age, check_only_age)
new_phone = safe_modify_input("新手机号:", edit_cust.phone, check_only_phone)
new_email = safe_modify_input("新邮箱:", edit_cust.email, check_only_email)
Customer.modify_customer(edit_id, new_name, new_gender, new_age, new_phone, new_email)
case "6":
print("感谢使用,系统已退出!")
break
case _:
print("输入无效!请输入1~6之间的数字选择功能\n")
更多推荐


所有评论(0)