题目:健身房会员与课程预约管理系统
一、背景与要求
请编写一个命令行交互程序,实现对健身房会员和团课预约的管理。程序启动后显示菜单,用户输入选项数字执行相应功能,直到选择退出。
数据存储要求:
1.使用一个字典 members 作为会员主数据容器,键为会员手机号(字符串,11位),值为另一个字典,包含:
name:姓名(字符串)
type:卡类型('月卡'、'季卡'、'年卡',字符串)
remain_days:剩余有效天数(整数)
points:积分余额(整数)
2.使用一个字典 courses 作为课程主数据容器,键为课程编号(字符串,格式如 C101),值为另一个字典,包含:
name:课程名称(字符串)
coach:教练姓名(字符串)
capacity:课程容量上限(整数)
booked:当前已预约人数(整数)
3.使用一个列表 reservations 记录每一次预约操作的日志,每条日志为元组,格式为:
('预约', 会员手机号, 会员姓名, 课程编号, 课程名称, 预约日期)
日期统一用字符串表示,如 '2026-04-13'
程序功能菜单:
text
1. 注册新会员
2. 查看所有会员
3. 查询会员信息
4. 续费会员卡
5. 添加新课程
6. 查看所有课程
7. 预约课程
8. 统计信息
9. 显示预约日志
10. 退出系统
功能具体要求:
功能 说明
注册新会员 输入手机号、姓名、卡类型(1=月卡/2=季卡/3=年卡)。若手机号已存在则提示错误并重新输入。根据卡类型设置初始剩余天数:月卡30天,季卡90天,年卡365天。初始积分为0。注册成功后显示提示信息。
查看所有会员 按手机号顺序打印每个会员的手机号、姓名、卡类型、剩余天数、积分。若无会员则提示“暂无会员信息”。
查询会员信息 输入手机号,若存在则显示该会员的详细信息和当前积分。若不存在则提示“会员不存在”。
续费会员卡 输入手机号,若不存在则提示错误;若存在则显示当前卡类型和剩余天数,然后输入续费类型(1/2/3)。续费后叠加对应的天数,并增加积分(月卡+50分,季卡+150分,年卡+600分)。续费成功后显示更新后的信息。
添加新课程 输入课程编号、课程名称、教练姓名、容量上限。若编号已存在则提示错误并重新输入。容量必须为正整数,初始已预约人数为0。添加成功后显示提示。
查看所有课程 按课程编号顺序打印每门课程的编号、名称、教练、容量、已预约人数、剩余名额。若无课程则提示“暂无课程信息”。
预约课程 输入会员手机号,若不存在则提示错误并返回;若存在但剩余天数 ≤ 0 则提示“会员卡已过期,无法预约”;否则继续输入课程编号。若课程不存在则提示错误;若课程已预约人数等于容量则提示“该课程已约满”;否则预约成功:课程已预约人数加1,会员积分增加10分,并记录一条预约日志到 reservations 列表中(日期输入格式 YYYY-MM-DD)。成功后显示“预约成功,积分+10”。
统计信息 输出以下统计内容:
- 会员总数,以及各卡类型(月卡/季卡/年卡)的会员人数
- 积分最高的会员信息(手机号、姓名、积分;若有多人并列则显示第一个)
- 预约率最高的课程信息(课程编号、名称、预约率,即 booked/capacity;若无课程则跳过)
- 剩余名额为0的课程列表(编号、名称;若无则提示“所有课程均有空位”)
显示预约日志 按时间顺序打印 reservations 中的每条记录,格式清晰。若无日志则提示“暂无预约记录”。
退出系统 结束程序。
二、函数设计约束(重点考察部分)
必须按以下函数划分来组织代码,每个函数负责明确的功能,主程序仅负责菜单调度与用户交互。
额外要求:
使用类型注解(如函数签名中所示)增强代码可读性。
在适当位置使用 if/elif/else 进行条件判断(例如菜单分支、手机号存在性、课程容量判断)。
在统计信息计算、遍历容器时必须使用循环(如 for 遍历字典的 items())。
对用户输入的卡类型和容量等进行合法性校验(非数字或超出范围时提示重新输入)。
日期格式不要求严格校验,但需按字符串正确记录。
# python代码
members ={
"19222167743":{"name":"苏亦昂","type":'季卡',"remain_days":90,"points":0},
"16622165490":{"name":"方洪","type":'月卡',"remain_days":30,"points":0},
}
courses ={
"C101":{"name":"卧推训练课程","coach":'颜回',"capacity":5,"booked":0},
"C102":{"name":"深蹲训练课程","coach":'仲文',"capacity":8,"booked":0},
}
reservations =[
('预约', '19222167743', '苏亦昂', 'C102', '深蹲训练课程', '2026-05-14'),
('预约', '16622165490', '方洪', 'C101', '卧推训练课程', '2026-04-15'),
]
"""
函数功能:注册新会员
参数:有,字典类型
返回值:无
功能完成
"""
def register_member(members: dict) -> None:
"""处理注册新会员逻辑,更新 members 字典"""
# 注册新会员 输入手机号、姓名、卡类型(1=月卡/2=季卡/3=年卡)。
# 若手机号已存在则提示错误并重新输入。
# 根据卡类型设置初始剩余天数:月卡30天,季卡90天,年卡365天。初始积分为0。注册成功后显示提示信息。
phone_num=input("注册新会员,请输入手机号:")
# 下面这while,确保,手机号唯一
while True:
#手机号正确,11位,数字
if len(phone_num) != 11 or not phone_num.isdigit():
phone_num=input("不是正确的手机号,11位数字,请重新输入:")
continue
if phone_num in members:
# 存在,循环继续
phone_num=input("手机号已存在,请重新输入:")
else:
# 添加
name=input("请输入姓名:")
remain_days=0
card_type=input("请入卡类型(1=月卡/2=季卡/3=年卡),输数字:")
# 下面while,确保正确输入卡类型,
while True:
if card_type=="1":
card_type="月卡"
remain_days=30
break
elif card_type=="2":
card_type="季卡"
remain_days=90
break
elif card_type=="3":
card_type="年卡"
remain_days=365
break
else:
card_type=input("没有这个类型!请重新输入:")
new_dict={"name":name,"type":card_type,"remain_days":remain_days,"points":0}
members[phone_num]=new_dict
print(f"""
注册成功!你注册的信息:
手机号:{phone_num}
姓名:{members[phone_num]["name"]}
类型:{members[phone_num]["type"]}
剩余天数:{members[phone_num]["remain_days"]}
积分:{members[phone_num]["points"]}
"""
)
# 新成员添加成功,外循环,结束
break
# 功能完成
def show_all_members(members: dict) -> None:
"""打印所有会员信息,若无会员则输出提示"""
# 查看所有会员 按手机号顺序打印每个会员的手机号、姓名、卡类型、剩余天数、积分。若无会员则提示“暂无会员信息”。
if not members:
print("暂无会员信息!")
else:
# 手机号,升序
phone_sorted=sorted(members,key=lambda a:int(a))
for key in phone_sorted:
print(f"""
会员信息:
手机号:{key}
姓名:{members[key]["name"]}
类型:{members[key]["type"]}
剩余天数:{members[key]["remain_days"]}
积分:{members[key]["points"]}
"""
)
# 功能完成
def query_member(members: dict) -> None:
"""按手机号查询并打印会员详细信息"""
# 查询会员信息 输入手机号,若存在则显示该会员的详细信息和当前积分。若不存在则提示“会员不存在”。
phone_num=input("请输入要查询的会员手机号:")
if phone_num in members:
print(f"""
查询成功!详细信息:
手机号:{phone_num}
姓名:{members[phone_num]["name"]}
类型:{members[phone_num]["type"]}
剩余天数:{members[phone_num]["remain_days"]}
积分:{members[phone_num]["points"]}
"""
)
else:
print(f"会员不存在!")
# 功能完成
def renew_membership(members: dict) -> None:
"""处理会员卡续费逻辑,更新剩余天数和积分"""
# 续费会员卡 输入手机号,若不存在则提示错误;
# 若存在则显示当前卡类型和剩余天数,然后输入续费类型(1/2/3)。
# 续费后叠加对应的天数,并增加积分(月卡+50分,季卡+150分,年卡+600分)。续费成功后显示更新后的信息。
phone_num=input("请输入续费会员的手机号:")
if phone_num in members:
print(f"""
类型:{members[phone_num]["type"]}
剩余天数:{members[phone_num]["remain_days"]}
""")
# 续费
card_type=input("请入续费类型(1=月卡/2=季卡/3=年卡),输数字:")
# 下面while,确保正确输入卡类型,
while True:
if card_type=="1":
members[phone_num]["type"]="月卡"
members[phone_num]["remain_days"]+=30
members[phone_num]["points"]+=50
break
elif card_type=="2":
members[phone_num]["type"]="季卡"
members[phone_num]["remain_days"]+=90
members[phone_num]["points"]+=150
break
elif card_type=="3":
members[phone_num]["type"]="年卡"
members[phone_num]["remain_days"]+=365
members[phone_num]["points"]+=600
break
else:
card_type=input("没有这个类型!请重新输入:")
print(f"""
续费成功!续费更新后的信息:
手机号:{phone_num}
姓名:{members[phone_num]["name"]}
类型:{members[phone_num]["type"]}
剩余天数:{members[phone_num]["remain_days"]}
积分:{members[phone_num]["points"]}
"""
)
else:
print(" 续费错误,不存在该会员!")
# 功能完成
def add_course(courses: dict) -> None:
"""处理添加新课程逻辑,更新 courses 字典"""
# 添加新课程 输入课程编号、课程名称、教练姓名、容量上限。
# 若编号已存在则提示错误并重新输入。
# 容量必须为正整数>0,初始已预约人数为0。添加成功后显示提示。
course_num=input("请输入添加新课程的编号:")
while True:
if course_num in courses:
course_num=input("编号已存在!请重新输入:")
else:
name=input("请输入课程名称:")
coach=input("请输入教练姓名:")
capacity=int(input("请输入容量上限:"))
# 下面的while,确保容量为正整数>0
while True:
if capacity>0:
break
else:
capacity=int(input("注意!容量必须为正整数:"))
new_dict={"name":name,"coach":coach,"capacity":capacity,"booked":0}
courses[course_num]=new_dict
print(f"""
课程添加成功!添加的课程信息:
课程编号:{course_num}
课程名称:{courses[course_num]["name"]}
教练姓名:{courses[course_num]["coach"]}
容量上限:{courses[course_num]["capacity"]}
已预约人数:{courses[course_num]["booked"]}
"""
)
break
# 功能完成
def show_all_courses(courses: dict) -> None:
"""打印所有课程信息,若无课程则输出提示"""
# 查看所有课程
# 按课程编号顺序打印每门课程的编号、名称、教练、容量、已预约人数、剩余名额。
# 若无课程则提示“暂无课程信息”。
if not courses:
print("暂无课程信息")
else:
# 升序
sorted_keys=sorted(courses.keys())
for course_num in sorted_keys:
print(f"""
查看成功!
课程编号:{course_num}
课程名称:{courses[course_num]["name"]}
教练姓名:{courses[course_num]["coach"]}
容量上限:{courses[course_num]["capacity"]}
已预约人数:{courses[course_num]["booked"]}
剩余名额:{courses[course_num]["capacity"]-courses[course_num]["booked"]}
"""
)
# 功能完成
def reserve_course(members: dict, courses: dict, reservations: list) -> None:
"""处理课程预约逻辑,更新课程已约人数、会员积分,并记录预约日志"""
# 预约课程 输入会员手机号,若不存在则提示错误并返回;
# 若存在但剩余天数 ≤ 0 则提示“会员卡已过期,无法预约”;
# 否则继续输入课程编号。若课程不存在则提示错误;
# 若课程已预约人数等于容量则提示“该课程已约满”;
# 否则预约成功:课程已预约人数加1,会员积分增加10分,并记录一条预约日志到 reservations 列表中(日期输入格式 YYYY-MM-DD)。
# 成功后显示“预约成功,积分+10”。
phone_num=input("请输入预约课程的会员手机号:")
if not phone_num in members:
print("不存在该会员!")
return
if members[phone_num]["remain_days"]<=0:
print("会员卡已过期,无法预约!")
return
# 会员卡还有天数
course_num=input("请输入你要预约的课程编号:")
if not course_num in courses:
# 不在课,错误
print("错误,课程不存在!")
else:
# 存在课
if courses[course_num]["capacity"]==courses[course_num]["booked"]:
print("该课程已约满!")
else:
courses[course_num]["booked"]+=1
members[phone_num]["points"]+=10
# 记录一条预约日志到列表中
new_log=('预约',phone_num,members[phone_num]["name"],course_num,courses[course_num]["name"],'2026-04-17')
reservations.append(new_log)
print("预约成功,积分+10")
# 我看看对不对
# print(f"""
# 查看成功!
# 课程编号:{course_num}
# 课程名称:{courses[course_num]["name"]}
# 教练姓名:{courses[course_num]["coach"]}
# 容量上限:{courses[course_num]["capacity"]}
# 已预约人数:{courses[course_num]["booked"]}
# 剩余名额:{courses[course_num]["capacity"]-courses[course_num]["booked"]}
# 手机号:{phone_num}
# 姓名:{members[phone_num]["name"]}
# 类型:{members[phone_num]["type"]}
# 剩余天数:{members[phone_num]["remain_days"]}
# 积分:{members[phone_num]["points"]}
# {reservations[-1]}
# """
# )
# 功能完成 ,这里要检查一下
def get_statistics(members: dict, courses: dict) -> dict:
"""
返回统计信息字典,包含:
- 'total_members': 会员总数
- 'type_counts': {'月卡': 人数, '季卡': 人数, '年卡': 人数}
- 'top_points_member': (手机号, 姓名, 积分) 或 None
- 'top_booking_course': (课程编号, 名称, 预约率) 或 None
- 'full_courses': 预约满的课程列表[],元素为 (编号, 名称)
"""
# 统计信息 输出以下统计内容:
# - 会员总数,以及各卡类型(月卡/季卡/年卡)的会员人数
# - 积分最高的会员信息(手机号、姓名、积分;若有多人并列则显示第一个)
# - 预约率最高的课程信息(课程编号、名称、预约率,即 booked/capacity;若无课程则跳过)
# - 剩余名额为0的课程列表(编号、名称;若无则提示“所有课程均有空位”)
total_members=0
type_counts={'月卡': 0, '季卡': 0, '年卡': 0}
top_points_member=None
phone_num=""
for key in members:
total_members+=1
if members[key]["type"]=='月卡':
type_counts['月卡']+=1
elif members[key]["type"]=='季卡':
type_counts['季卡']+=1
else:
type_counts['年卡']+=1
top_points=0
if members[key]["points"]>top_points:
top_points = members[key]["points"]
phone_num=key
if phone_num=="":
top_points_member=None
else:
# 元组
top_points_member=(phone_num,members[phone_num]["name"],members[phone_num]["points"])
# - 预约率最高的课程信息(课程编号、名称、预约率,即 booked/capacity;若无课程则跳过)
# - 剩余名额为0的课程列表(编号、名称;若无则提示“所有课程均有空位”)
max_booked=""
booked_rate=0
full_courses=[]
for key in courses:
capacity=courses[key]["capacity"]
booked=courses[key]["booked"]
if capacity-booked==0:
new_tuple=(key,courses[key]["name"])
full_courses.append(new_tuple)
if booked/capacity>booked_rate:
booked_rate=booked/capacity
max_booked=key
if max_booked=="":
top_booking_course="无课程,跳过!"
else:
top_booking_course=(max_booked,courses[max_booked]["name"],booked_rate)
if full_courses==[]:
full_courses="所有课程均有空位!"
result={
'total_members': total_members,
'type_counts': type_counts,
'top_points_member':top_points_member,
'top_booking_course': top_booking_course,
'full_courses':full_courses,
}
return result
# 功能完成
def show_statistics(members: dict, courses: dict) -> None:
"""调用 get_statistics 并格式化打印统计结果"""
result=get_statistics(members,courses)
for key,val in result.items():
print(f"{key}:{val}")
# 功能完成
def show_reservations(reservations: list) -> None:
"""打印所有预约操作日志"""
# 显示预约日志 按时间顺序打印 reservations 中的每条记录,格式清晰。
# 若无日志则提示“暂无预约记录”。
if not reservations:
print("暂无预约记录")
else:
# 时间顺序,升序
sorted_date=sorted(reservations,key=lambda a:a[-1])
for i in sorted_date:
print(i)
menu='''
程序功能菜单:
1. 注册新会员
2. 查看所有会员
3. 查询会员信息
4. 续费会员卡
5. 添加新课程
6. 查看所有课程
7. 预约课程
8. 统计信息
9. 显示预约日志
10. 退出系统
'''
def main():
"""主菜单循环"""
while True:
print(menu)
choose=input("请输入你的选择:")
if choose=="1":
register_member(members)
elif choose=="2":
show_all_members(members)
elif choose=="3":
query_member(members)
elif choose=="4":
renew_membership(members)
elif choose=="5":
add_course(courses)
elif choose=="6":
show_all_courses(courses)
elif choose=="7":
reserve_course(members, courses, reservations)
elif choose=="8":
show_statistics(members,courses)
elif choose=="9":
show_reservations(reservations)
elif choose=="10":
print("退出成功!")
break
else:
print("没有这个选择!")
# 调用主函数,这是入口
main()