Python教程42:综合项目-图书管理系统 “纸上得来终觉浅,绝知此事要躬行。”
经过第四部分12课的学习,我们掌握了OOP的核心概念。今天通过一个完整的图书管理系统,综合运用所学知识。
1. 项目需求 功能需求 基本功能:
图书管理:添加、删除、搜索、借阅、归还 用户管理:注册、借阅记录 分类管理:按类别组织图书 进阶功能:
数据持久化(JSON) 借阅期限和逾期管理 统计报表 技术要求 使用类和对象 继承和多态 抽象基类 属性管理(@property) 异常处理 文件操作 2. 系统设计 类设计 Library System ├── Book(图书基类) │ ├── PhysicalBook(实体书) │ └── EBook(电子书) ├── User(用户类) ├── Library(图书馆类) ├── BorrowRecord(借阅记录) └── Storage(存储类) 3. 核心实现 Book基类 1from abc import ABC, abstractmethod 2from datetime import datetime 3 4class Book(ABC): 5 """图书抽象基类""" 6 7 def __init__(self, isbn, title, author, category): 8 self.isbn = isbn 9 self.title = title 10 self.author = author 11 self.category = category 12 self.is_borrowed = False 13 14 @abstractmethod 15 def get_type(self): 16 """获取图书类型""" 17 pass 18 19 def to_dict(self): 20 """序列化""" 21 return { 22 'isbn': self.isbn, 23 'title': self.title, 24 'author': self.author, 25 'category': self.category, 26 'is_borrowed': self.is_borrowed, 27 'type': self.get_type() 28 } 29 30 def __str__(self): 31 status = "已借出" if self.is_borrowed else "可借阅" 32 return f"{self.title} by {self.author} ({status})" 33 34class PhysicalBook(Book): 35 """实体书""" 36 def __init__(self, isbn, title, author, category, location): 37 super().__init__(isbn, title, author, category) 38 self.location = location # 书架位置 39 40 def get_type(self): 41 return "physical" 42 43 def to_dict(self): 44 data = super().to_dict() 45 data['location'] = self.location 46 return data 47 48class EBook(Book): 49 """电子书""" 50 def __init__(self, isbn, title, author, category, file_size): 51 super().__init__(isbn, title, author, category) 52 self.file_size = file_size # 文件大小(MB) 53 54 def get_type(self): 55 return "ebook" 56 57 def to_dict(self): 58 data = super().to_dict() 59 data['file_size'] = self.file_size 60 return data User类 1class User: 2 """用户类""" 3 4 def __init__(self, user_id, name, email): 5 self.user_id = user_id 6 self.name = name 7 self.email = email 8 self.borrowed_books = [] # ISBN列表 9 10 def can_borrow(self, max_books=5): 11 """检查是否可以借阅""" 12 return len(self.borrowed_books) < max_books 13 14 def borrow_book(self, isbn): 15 """借阅图书""" 16 if isbn not in self.borrowed_books: 17 self.borrowed_books.append(isbn) 18 19 def return_book(self, isbn): 20 """归还图书""" 21 if isbn in self.borrowed_books: 22 self.borrowed_books.remove(isbn) 23 24 def to_dict(self): 25 return { 26 'user_id': self.user_id, 27 'name': self.name, 28 'email': self.email, 29 'borrowed_books': self.borrowed_books 30 } 31 32 def __str__(self): 33 return f"User({self.name}, 已借{len(self.borrowed_books)}本)" BorrowRecord类 1class BorrowRecord: 2 """借阅记录""" 3 4 def __init__(self, user_id, isbn, borrow_date=None): 5 self.user_id = user_id 6 self.isbn = isbn 7 self.borrow_date = borrow_date or datetime.now() 8 self.return_date = None 9 self.due_date = self.borrow_date + timedelta(days=30) 10 11 @property 12 def is_overdue(self): 13 """是否逾期""" 14 if self.return_date: 15 return False 16 return datetime.now() > self.due_date 17 18 def mark_returned(self): 19 """标记为已归还""" 20 self.return_date = datetime.now() 21 22 def to_dict(self): 23 return { 24 'user_id': self.user_id, 25 'isbn': self.isbn, 26 'borrow_date': self.borrow_date.isoformat(), 27 'due_date': self.due_date.isoformat(), 28 'return_date': self.return_date.isoformat() if self.return_date else None 29 } Library类 1class Library: 2 """图书馆类""" 3 4 def __init__(self, name): 5 self.name = name 6 self.books = {} # ISBN -> Book 7 self.users = {} # user_id -> User 8 self.records = [] # BorrowRecord列表 9 10 def add_book(self, book): 11 """添加图书""" 12 if book.isbn in self.books: 13 raise ValueError(f"图书{book.isbn}已存在") 14 self.books[book.isbn] = book 15 16 def remove_book(self, isbn): 17 """删除图书""" 18 if isbn not in self.books: 19 raise ValueError(f"图书{isbn}不存在") 20 if self.books[isbn].is_borrowed: 21 raise ValueError("图书已借出,无法删除") 22 del self.books[isbn] 23 24 def register_user(self, user): 25 """注册用户""" 26 if user.user_id in self.users: 27 raise ValueError(f"用户{user.user_id}已存在") 28 self.users[user.user_id] = user 29 30 def borrow_book(self, user_id, isbn): 31 """借阅图书""" 32 # 验证 33 if user_id not in self.users: 34 raise ValueError("用户不存在") 35 if isbn not in self.books: 36 raise ValueError("图书不存在") 37 38 user = self.users[user_id] 39 book = self.books[isbn] 40 41 if book.is_borrowed: 42 raise ValueError("图书已被借出") 43 if not user.can_borrow(): 44 raise ValueError("借阅数量已达上限") 45 46 # 借阅 47 book.is_borrowed = True 48 user.borrow_book(isbn) 49 record = BorrowRecord(user_id, isbn) 50 self.records.append(record) 51 52 return f"{user.name}成功借阅《{book.title}》" 53 54 def return_book(self, user_id, isbn): 55 """归还图书""" 56 if user_id not in self.users: 57 raise ValueError("用户不存在") 58 if isbn not in self.books: 59 raise ValueError("图书不存在") 60 61 user = self.users[user_id] 62 book = self.books[isbn] 63 64 if not book.is_borrowed: 65 raise ValueError("图书未被借出") 66 67 # 归还 68 book.is_borrowed = False 69 user.return_book(isbn) 70 71 # 更新记录 72 for record in reversed(self.records): 73 if (record.user_id == user_id and 74 record.isbn == isbn and 75 not record.return_date): 76 record.mark_returned() 77 break 78 79 return f"{user.name}成功归还《{book.title}》" 80 81 def search_books(self, keyword): 82 """搜索图书""" 83 results = [] 84 keyword = keyword.lower() 85 for book in self.books.values(): 86 if (keyword in book.title.lower() or 87 keyword in book.author.lower() or 88 keyword in book.category.lower()): 89 results.append(book) 90 return results 91 92 def get_statistics(self): 93 """获取统计信息""" 94 total_books = len(self.books) 95 borrowed = sum(1 for book in self.books.values() if book.is_borrowed) 96 overdue = sum(1 for record in self.records if record.is_overdue) 97 98 return { 99 'total_books': total_books, 100 'available': total_books - borrowed, 101 'borrowed': borrowed, 102 'total_users': len(self.users), 103 'overdue_records': overdue 104 } 4. 使用示例 1# 创建图书馆 2library = Library("市图书馆") 3 4# 添加图书 5book1 = PhysicalBook("978-1", "Python编程", "作者A", "编程", "A-101") 6book2 = EBook("978-2", "数据结构", "作者B", "编程", 15.5) 7library.add_book(book1) 8library.add_book(book2) 9 10# 注册用户 11user = User("U001", "张三", "zhang@example.com") 12library.register_user(user) 13 14# 借阅流程 15print(library.borrow_book("U001", "978-1")) 16print(library.borrow_book("U001", "978-2")) 17 18# 搜索 19results = library.search_books("Python") 20for book in results: 21 print(book) 22 23# 统计 24stats = library.get_statistics() 25print(f"总藏书:{stats['total_books']}") 26print(f"可借阅:{stats['available']}") 27print(f"已借出:{stats['borrowed']}") 28 29# 归还 30print(library.return_book("U001", "978-1")) 5. 知识点回顾 这个项目运用了:
...