实战-图书管理系统

实战-图书管理系统

2026年9月20日·#编程学习/python学习笔记Python/面向对象·1582 字 8 分钟
浏览量加载中...
AI 摘要

用面向对象做图书管理系统:抽象类 Member 与子类权限设计、Book 库存管理、JSON 数据加载与主循环

需求#

某社区图书馆要开发一个简单的图书管理系统,支持会员登录、图书借阅、图书归还。

功能说明
会员登录卡号 + 密码登录,登录成功后才能使用系统
借书借阅库存有余量的图书
还书归还已借阅的图书
查看我的借阅展示当前会员已借阅的图书列表
退出系统

借阅规则:普通会员最多借 3 本;VIP 会员最多借 6 + VIP等级 本(等级默认 1)。库存不足或已达上限时不能借。

类的设计#

职责
Book一本书:编号、标题、作者、总数、可用数量(私有);借出/归还/查可用
Member(抽象类)会员公共部分:卡号、姓名、密码(私有)借阅列表(私有);借书/还书/取密码/取借阅列表;抽象方法 get_max_books()
NormalMember普通会员:get_max_books() 返回 3
VIPMemberVIP 会员:多一个 vip_levelget_max_books() 返回 6 + vip_level
LibrarySystem图书馆系统:加载数据、登录、借书、还书、查看借阅、主循环

抽象类:规定子类必须实现什么#

from abc import ABC, abstractmethod
class Member(ABC): # 继承 ABC(Abstract Base Class)
...
@abstractmethod
def get_max_books(self) -> int:
pass # 只有声明,没有实现
Important

抽象类是一种只能被继承、不能被直接实例化的类,作用是规定子类必须实现哪些方法,强制子类遵守统一的代码规范。Python 里的抽象类需要继承 abc 模块的 ABC,抽象方法用 @abstractmethod 装饰。 在这里它的价值是:Member 自己说不清”最多能借几本”,但要求每个子类必须说清楚。

关键代码#

图书:私有可用数量 + 借还#

class Book:
def __init__(self, book_id, title, author, total_num):
self.book_id = book_id
self.title = title
self.author = author
self.total_num = total_num
self.__available_num = total_num # 可用数量(私有)
def borrow_book(self):
if self.__available_num > 0:
self.__available_num -= 1
return True
return False
def return_book(self):
self.__available_num += 1
def get_available_num(self):
return self.__available_num

会员:借书时先查上限,再查库存#

class Member(ABC):
def borrow_book(self, book: Book):
# 1. 达到最大借阅数量就不给借
if len(self.__borrowed_books) >= self.get_max_books():
print("借阅失败,您的借阅数量已达到最大限制!")
return False
# 2. 书籍还有余量才借
if book.borrow_book():
self.__borrowed_books.append(book)
print(f"{self.name} 已成功借阅图书 {book.title}")
return True
else:
print(f"借阅失败,图书 {book.title} 已被借完!")
return False

两种会员:用多态实现”上限不同”#

class NormalMember(Member):
def get_max_books(self) -> int:
return 3
class VIPMember(Member):
def __init__(self, member_id, name, password, vip_level):
super().__init__(member_id, name, password)
self.vip_level = vip_level
def get_max_books(self) -> int:
return 6 + self.vip_level

系统:从 JSON 加载数据(按卡号前缀判断会员类型)#

class LibrarySystem:
def __init__(self):
self.books = {} # {"AI001": Book对象, ...}
self.members = {} # {"V001": Member对象, ...}
self.current_member: Member | None = None
self.load_books_data()
self.load_members_data()
def load_members_data(self):
with open("data/members.json", "r", encoding="utf-8") as f:
members_data = json.load(f)
for member in members_data:
if member['卡号'].startswith('N'):
self.members[member['卡号']] = NormalMember(member['卡号'], member['姓名'], member['密码'])
elif member['卡号'].startswith('V'):
self.members[member['卡号']] = VIPMember(member['卡号'], member['姓名'], member['密码'], member['会员等级'])

数据结构对应关系:books.json 里是 [{"编号","标题","作者","数量"}, ...]members.json 里是 [{"卡号","姓名","密码","会员等级"}, ...](普通会员没有”会员等级”字段)。

主循环#

def run(self):
if self.login(): # 登录成功才进菜单
while True:
print("1. 借阅图书 2. 归还图书 3. 查看借阅 4. 退出系统")
choice = input("请选择操作(1-4): ")
match choice:
case "1": self.borrow_book()
case "2": self.return_book()
case "3": self.show_borrowed_books()
case "4":
print("退出系统, Bye Bye ~")
break
case _: print("无效的选项,请重新选择!")

相关#

练习题#

一、回忆填空(写完再展开按答案)#

  1. 抽象类需要继承 abc 模块的 ____ 类,抽象方法用 @____ 装饰
  2. 抽象类的作用:规定子类 ____;它本身 ____(能/不能)被直接实例化
  3. 普通会员最多借 ____ 本;VIP 会员最多借 ____ 本
  4. 借书时要先判断会员的 ____ 是否达到上限,再判断图书的 ____ 是否足够
  5. 加载会员数据时,用卡号的 ____ 判断是普通会员还是 VIP(N 开头/V 开头)
  6. 图书的可用数量设为 ____ 属性,对外通过 get_available_num() 读取
  7. LibrarySystemself.booksself.members 都是 ____(类型),键是编号/卡号,值是对象
填空答案(做完再点开)
  1. ABC / abstractmethod 2. 必须实现哪些方法 / 不能 3. 3 / 6 + VIP等级 4. 已借数量 / 库存(可用数量) 5. 前缀(startswith) 6. 私有 7. 字典

二、裸写题#

  • 2-1 两种会员的借阅上限NormalMember(上限 3)和 VIPMember(上限 6 + 等级),都继承抽象类 Member;分别实例化并打印各自的上限。

    提示(先自己想,实在想不出再点开)

    一级 · 思路:父类定规矩(抽象方法),子类各自给答案 二级 · 方法class Member(ABC) + @abstractmethod def get_max_books(self) 三级 · 骨架:VIP 的 __init__ 里先 super().__init__(...) 再存 vip_level

  • 2-2 图书库存Book 类:总数量 + 私有可用数量;borrow_book() 库存为 0 时返回 False,return_book() 归还加一。

    提示

    一级 · 思路:可用数量只让类内部改,外面只能读 二级 · 方法self.__available_num / get_available_num() 三级 · 骨架if self.__available_num > 0: self.__available_num -= 1; return True

  • 2-3 借书流程Memberborrow_book(book):先判断是否达到上限,再调用书的 borrow_book();达到上限时打印提示并返回 False。

    提示

    一级 · 思路:两道关卡,先自己的额度、再书的库存 二级 · 方法len(self.get_borrowed_books()) >= self.get_max_books() 三级 · 骨架:借成功要 append 到借阅列表里

参考答案(做完再点开)
from abc import ABC, abstractmethod
class Book:
def __init__(self, book_id, title, author, total_num):
self.book_id = book_id
self.title = title
self.author = author
self.total_num = total_num
self.__available_num = total_num
def borrow_book(self):
if self.__available_num > 0:
self.__available_num -= 1
return True
return False
def return_book(self):
self.__available_num += 1
def get_available_num(self):
return self.__available_num
class Member(ABC):
def __init__(self, member_id, name, password):
self.member_id = member_id
self.name = name
self.__password = password
self.__borrowed_books = []
def borrow_book(self, book: Book):
if len(self.__borrowed_books) >= self.get_max_books():
print(f"{self.name} 借阅失败,已达到最大借阅数量 {self.get_max_books()} 本")
return False
if book.borrow_book():
self.__borrowed_books.append(book)
print(f"{self.name} 已成功借阅图书 {book.title}")
return True
print(f"{self.name} 借阅失败,图书 {book.title} 已被借完")
return False
def get_borrowed_books(self):
return self.__borrowed_books
@abstractmethod
def get_max_books(self) -> int:
pass
class NormalMember(Member):
def get_max_books(self) -> int:
return 3
class VIPMember(Member):
def __init__(self, member_id, name, password, vip_level):
super().__init__(member_id, name, password)
self.vip_level = vip_level
def get_max_books(self) -> int:
return 6 + self.vip_level
# 测试
normal = NormalMember("N001", "小王", "123456")
vip = VIPMember("V001", "王林", "666888", 6)
print(normal.get_max_books(), vip.get_max_books()) # 3 12
book = Book("AI001", "LangChain入门与实践", "李智慧", 2)
for i in range(4):
normal.borrow_book(book) # 第 4 次会因达到上限而失败
print("剩余库存:", book.get_available_num())
book.return_book()
print("归还后剩余:", book.get_available_num())

评论区

[ 标签 ]
# AI37# AI 编程2# AI工具1# Ajax2# Apifox1# AstrBot3# Astro2# CC Switch1# CDN2# Claude Code1# claudecode2# ClaudeCode1# Cloudflare2# CloudFlare2# CloudFlare-ImgBed3# coc3# CSS6# DeepSeek6# deepseek2# DELETE1# Docker1# EdgeOne3# Gist1# git1# GitHub1# hexo-circle-of-friends1# HTML6# HTTP5# ImageManager1# Java23# java13# JavaScript5# JDBC3# JSON2# JUnit1# LangChain25# Logback1# Maven6# Muse Spark1# Mybatis1# MyBatis4# MySQL28# MySql1# NapCat1# Node.js1# obsidian2# Obsidian5# OpenCode4# ORM1# PathVariable1# PicGo1# PyCharm1# Python65# RequestBody1# RequestMapping1# RESTful风格1# skills1# Slf4j1# SpringBoot11# SQL2# Streamlit5# Svelte2# TailwindCSS1# Telegram3# Tlias2# Vercel1# vscode2# Vue7# Waline3# WebDAV1# Web基础6# Web开发6# WinSCP1# YAML1# 三层架构1# 中二宣言1# 书籍1# 使用文档10# 写作1# 函数2# 刷步数1# 前端32# 动态1# 动漫1# 包1# 单词2# 博客7# 博客工作流1# 博客开发2# 参数接收1# 友链1# 反思2# 图床6# 地图1# 备份2# 大模型1# 奇思妙想1# 存储1# 学习方法6# 学校1# 宝塔面板3# 宝宝10# 对象1# 导航栏1# 工具2# 开发1# 开发工具1# 开发规范1# 开心1# 异常处理1# 影视2# 微信1# 性能优化2# 总结1# 想法15# 感受1# 感悟11# 指南1# 提示词工程1# 插件5# 故障排除1# 效率工具2# 教程10# 数据分析9# 数据库27# 数据结构1# 文件操作2# 斩神1# 日常92# 日志框架1# 朋友圈1# 朱元璋1# 模块1# 模板1# 正则表达式2# 测试1# 游戏2# 爬虫7# 生活迁移1# 电影2# 电脑1# 碎碎念1# 视觉识别1# 类1# 类型注解1# 网络基础2# 网络教室1# 羊毛2# 脚本2# 脚本工具1# 自动化2# 蓝奏云1# 订阅推荐2# 记录2# 评论系统1# 词根1# 词缀1# 说说1# 足迹1# 跑步2# 路径参数1# 转载2# 运动1# 部落冲突1# 配置1# 随机图1# 面向对象5# 音乐3# 音标1# 饮食1# 驼峰命名1# 高德地图1
[ 公告 ]

如果你喜欢,那么欢迎来到我的世界!

了解更多
[ 音乐 ]
封面

音乐

暂未播放

0:000:00
暂无歌词
找不到相关结果。
[ contents ]
[ 全部文章 ]