当前位置: 首页 > news >正文

(Python)类的练习与巩固(图书管理系统扩展)(类与方法的基础教程)(if条件扩展)(动态类型)(Python教程)

目录

源代码:

代码详解:

新需求

步骤引导

第一步:创建 Student 类并初始化属性

第二步:给 Student 类添加 “借阅图书” 方法

第三步:添加 “归还图书” 方法

第四步:添加 “查看已借图书” 方法

第五步:整合两个类并测试

运行结果说明

核心知识点

多说一句(重点代码解析):

1.学生类的def borrow_book()方法,和图书类的方法不是重名了吗?

1. 方法属于不同的类,作用域不同

2. 调用方式不同,不会冲突

3. 这样设计更符合 “自然语言”

举个生活中的例子

2.if book in self.borrowed_books:有没有其他表现形式? 

方法 1:用循环遍历判断

方法 2:用列表的 count() 方法

方法 3:用 any() 函数配合生成器

哪种最好?

3.for book in self.borrowed_books: 是什么?

举个例子

4.if book.is_available():if self.borrowed_books:为什么判断不用加条件?

先看 if self.borrowed_books:

再看 if book.is_available():

为什么可以这样写?


源代码:

class Book:def __init__(self,title,author,publisher,is_borrowed=False):self.title=titleself.author=authorself.publisher=publisherself.is_borrowed=is_borroweddef show_info(self):status="已借出"if self.is_borrowed==True else"未借出"print(f"书名:《{self.title}》")print(f"作者:{self.author}")print(f"出版社:{self.publisher}")print(f"状态:{status}")def borrow_book(self):if self.is_borrowed==False:self.is_borrowed=True print(f"《{self.title}》已经成功借出")else:print(f"抱歉《{self.title}》已经借出,无法再次借出")def return_book(self):if self.is_borrowed==True:self.is_borrowed=Falseprint(f"《{self.title}》已经成功归还")else:print(f"抱歉《{self.title}》未曾借出,无需归还")def is_available(self):if self.is_borrowed==False :print(f"《{self.title}》未曾借出")else:print(f"抱歉《{self.title}》已经借出")class Student:def __init__(self,name,student_id):self.name=nameself.student_id=student_idself.borrowed_books=[]def borrow_book(self,book):if book.is_available():book.borrow_book()self.borrowed_books.append(book)print(f"{self.name}成功借阅《{book.title}》")else:print(f"{self.name}无法借阅《{book.title}》,该书已被借出")def return_book(self,book):if book in self.borrowed_books:book.return_book()self.borrowed_books.remove(book)print(f"{self.name}成功归还《{book.title}》")else:print(f"{self.name}没有借阅《{book.title}》,无法归还")def show_borrowed_books(self):if self.borrowed_books:print(f"\n{self.name}(学号:{self.student_id})当前借阅的图书:")for book in self.borrowed_books:print(f"- 《{book.title}》")else:print(f"\n{self.name}当前没有借阅任何图书")book1 = Book("Python入门", "张三", "编程出版社")
book2 = Book("数据结构与算法", "李四", "科技出版社")
student = Student("小明", "2023001")
student.show_borrowed_books()
student.borrow_book(book1)
student.borrow_book(book2)
student.show_borrowed_books()
student.borrow_book(book1)
student.return_book(book1)
student.show_borrowed_books()

代码详解:

新需求

  1. 创建 Student 类,包含属性:姓名、学号、已借图书列表(初始为空)
  2. 给学生类添加方法:借阅图书、归还图书、查看已借图书
  3. 让学生类和图书类联动:学生借阅图书时,图书状态改为 “已借出”;归还时改为 “未借出”

步骤引导

第一步:创建 Student 类并初始化属性

先定义学生的基本信息,重点是 borrowed_books 列表(用来记录学生借了哪些书):

class Student:def __init__(self, name, student_id):self.name = name  # 学生姓名self.student_id = student_id  # 学号(唯一标识)self.borrowed_books = []  # 已借图书列表,初始为空
第二步:给 Student 类添加 “借阅图书” 方法

学生借阅图书时,需要做这些检查:

  • 图书是否可借(未被借出)
  • 如果可借,将图书添加到学生的借阅列表
  • 同时修改图书的借出状态(调用图书类的 borrow_book 方法)
class Student:def __init__(self, name, student_id):self.name = nameself.student_id = student_idself.borrowed_books = []# 借阅图书的方法(参数是一本图书对象)def borrow_book(self, book):# 检查图书是否可借if book.is_available():# 调用图书的borrow_book方法(修改图书状态)book.borrow_book()# 将图书添加到学生的借阅列表self.borrowed_books.append(book)print(f"{self.name}成功借阅《{book.title}》")else:print(f"{self.name}无法借阅《{book.title}》,该书已被借出")
第三步:添加 “归还图书” 方法

归还图书时,需要:

  • 检查学生是否真的借了这本书
  • 如果借了,从借阅列表中移除
  • 同时修改图书的状态(调用图书类的 return_book 方法)
class Student:def __init__(self, name, student_id):self.name = nameself.student_id = student_idself.borrowed_books = []def borrow_book(self, book):if book.is_available():book.borrow_book()self.borrowed_books.append(book)print(f"{self.name}成功借阅《{book.title}》")else:print(f"{self.name}无法借阅《{book.title}》,该书已被借出")# 归还图书的方法(参数是一本图书对象)def return_book(self, book):# 检查这本书是否在学生的借阅列表中if book in self.borrowed_books:# 调用图书的return_book方法(修改图书状态)book.return_book()# 从借阅列表中移除self.borrowed_books.remove(book)print(f"{self.name}成功归还《{book.title}》")else:print(f"{self.name}没有借阅《{book.title}》,无法归还")
第四步:添加 “查看已借图书” 方法
class Student:def __init__(self, name, student_id):self.name = nameself.student_id = student_idself.borrowed_books = []def borrow_book(self, book):if book.is_available():book.borrow_book()self.borrowed_books.append(book)print(f"{self.name}成功借阅《{book.title}》")else:print(f"{self.name}无法借阅《{book.title}》,该书已被借出")def return_book(self, book):if book in self.borrowed_books:book.return_book()self.borrowed_books.remove(book)print(f"{self.name}成功归还《{book.title}》")else:print(f"{self.name}没有借阅《{book.title}》,无法归还")# 查看已借图书def show_borrowed_books(self):if self.borrowed_books:  # 如果有已借图书print(f"\n{self.name}(学号:{self.student_id})当前借阅的图书:")for book in self.borrowed_books:print(f"- 《{book.title}》")else:  # 如果没有借书print(f"\n{self.name}当前没有借阅任何图书")
第五步:整合两个类并测试

现在我们有了 Book 类(之前修正过的)和 Student 类,来测试它们的交互:

# 创建两本图书book1 = Book("Python入门", "张三", "编程出版社")book2 = Book("数据结构与算法", "李四", "科技出版社")# 创建一个学生student = Student("小明", "2023001")# 查看学生初始借阅情况student.show_borrowed_books()# 学生借阅第一本书student.borrow_book(book1)# 学生尝试借阅第二本书student.borrow_book(book2)# 查看借阅情况student.show_borrowed_books()# 学生尝试再次借阅第一本书(应该失败)student.borrow_book(book1)# 学生归还第一本书student.return_book(book1)# 查看最终借阅情况student.show_borrowed_books()

运行结果说明

小明当前没有借阅任何图书
《Python入门》状态更新为:已借出
小明成功借阅《Python入门》
《数据结构与算法》状态更新为:已借出
小明成功借阅《数据结构与算法》小明(学号:2023001)的借阅列表:
1. 《Python入门》
2. 《数据结构与算法》
《Python入门》已被借出
小明无法借阅《Python入门》,该书已被借出
《Python入门》状态更新为:未借出
小明成功归还《Python入门》小明当前没有借阅任何图书

核心知识点

  1. 类的交互:学生类通过调用图书类的方法(borrow_bookreturn_book)来修改图书状态,体现了对象之间的协作。
  2. 对象存储:学生的 borrowed_books 列表直接存储图书对象,而不是字符串,这样可以直接操作图书的属性和方法。
  3. 逻辑检查:借阅 / 归还前的条件判断(是否可借、是否真的借出)让程序更严谨。

多说一句(重点代码解析):

1.学生类的def borrow_book()方法,和图书类的方法不是重名了吗?

1. 方法属于不同的类,作用域不同

  • 图书类的 borrow_book 是图书自己的方法,作用是 “修改自己的借出状态”(比如从 “未借出” 变成 “已借出”)
  • 学生类的 borrow_book 是学生自己的方法,作用是 “学生执行借阅操作”(比如检查图书是否可借、把图书加入自己的借阅列表)

它们虽然名字一样,但属于不同的类,就像两个同名的人分别在两个不同的班级,不会混淆。

2. 调用方式不同,不会冲突

调用时需要通过具体的对象,所以能明确区分:

# 调用图书的borrow_book(图书自己修改状态)
book1.borrow_book()# 调用学生的borrow_book(学生执行借阅操作,参数是图书对象)
student1.borrow_book(book1)

3. 这样设计更符合 “自然语言”

比如我们说:

  • “这本书被借出了” → 对应 book.borrow_book()
  • “这个学生借了这本书” → 对应 student.borrow_book(book)

用相同的名字反而更符合我们的表达习惯,一看就知道是和 “借阅” 相关的操作。

举个生活中的例子

就像:

  • 手机有 “充电” 功能(手机自己的方法:接收充电)
  • 人有 “充电” 动作(人的方法:给手机充电)

虽然都叫 “充电”,但一个是手机的行为,一个是人的行为,完全不冲突,反而很容易理解~

所以这种 “同名不同类” 的方法在编程中是合理且常用的,不用特意修改名字哦!

2.if book in self.borrowed_books:有没有其他表现形式? 

方法 1:用循环遍历判断

通过遍历 borrowed_books 列表,逐个对比是否为目标图书:

# 遍历借阅列表中的每一本书
has_book = False  # 先假设没有
for b in self.borrowed_books:if b == book:  # 对比当前书和目标书是否是同一本has_book = Truebreak  # 找到后就跳出循环if has_book:# 执行归还操作...
else:print(f"{self.name}没有借阅《{book.title}》,无法归还")

这种方式更直观地展示了 “检查包含” 的底层逻辑,但代码比 in 关键字更长。

方法 2:用列表的 count() 方法

count(book) 会返回列表中与 book 匹配的元素数量,如果大于 0,说明包含这本书:

if self.borrowed_books.count(book) > 0:# 执行归还操作...
else:print(f"{self.name}没有借阅《{book.title}》,无法归还")

原理和 in 类似,但 count() 会遍历整个列表(即使找到匹配项也会继续检查),效率略低于 inin 找到后会立即停止)。

方法 3:用 any() 函数配合生成器

any() 函数判断是否有任意一个元素满足条件,这里检查是否有一本书等于目标书:

if any(b == book for b in self.borrowed_books):# 执行归还操作...
else:print(f"{self.name}没有借阅《{book.title}》,无法归还")

这种方式更偏向函数式编程风格,和 in 的效率相近。

哪种最好?

if book in self.borrowed_books: 是最简洁、高效且符合 Python 风格的写法,日常开发中优先使用这种。其他方式更多是帮助理解 “检查包含” 的不同实现思路,实际场景中很少需要替换。

本质上,这些方法都是基于 “对象身份” 判断的 —— 因为 borrowed_books 中存储的是图书对象本身,所以 book in 列表 会直接判断是否为同一个对象(而不是比较属性是否相同),这正是我们需要的逻辑~

3.for book in self.borrowed_books: 是什么?

这行代码是 for 循环遍历列表 的操作,作用是依次取出学生借阅列表中的每本图书,并打印出图书的标题。

我们拆解来看:

  1. for book in self.borrowed_books:

    • self.borrowed_books 是存储学生已借图书的列表(里面放的是 Book 类的实例对象)。
    • 这行的意思是:依次从借阅列表中取出每一个元素,暂时用变量 book 表示(每次循环,book 就代表列表中的一本书)。
  2. print(f"- 《{book.title}》")

    • 循环内部,对当前取出的 book(一本图书对象)进行操作。
    • book.title 是访问这本书的 title 属性(即书名)。
    • 用 f - 字符串格式化后,打印出类似 - 《Python入门》 这样的内容。

举个例子

如果学生的借阅列表是:
self.borrowed_books = [book1, book2](其中 book1 是《Python 入门》,book2 是《小王子》)

循环会分两次执行:

  • 第一次:book 代表 book1 → 打印 - 《Python入门》
  • 第二次:book 代表 book2 → 打印 - 《小王子》

简单说,这行代码的作用就是 “把学生借的所有书,一本一本列出来打印”,让我们能清晰看到学生借了哪些书~

4.if book.is_available():if self.borrowed_books:为什么判断不用加条件?

这是 Python 中一种简洁的 “真值判断” 写法,利用了数据类型的 “布尔特性”—— 不同类型的数据会被自动判断为 “真(True)” 或 “假(False)”,所以不需要额外加条件。

先看 if self.borrowed_books:

self.borrowed_books 是一个列表:

  • 当列表为空时([]),Python 会把它视为 “假(False)”
  • 当列表有元素时(比如 [book1, book2]),会被视为 “真(True)”

所以 if self.borrowed_books: 等价于 if len(self.borrowed_books) > 0:,意思是 “如果借阅列表里有书”。

再看 if book.is_available():

book.is_available() 是一个返回布尔值(True/False)的方法:

  • 当图书可借时,这个方法返回 True
  • 当图书不可借时,返回 False

所以 if book.is_available(): 等价于 if book.is_available() == True:,直接用返回的布尔值作为判断条件。

为什么可以这样写?

Python 的设计理念是 “简洁明了”,对于这些常见判断,允许省略冗余的条件:

  • 列表、字符串、字典等 “容器类型”:空则为假,非空则为真
  • 布尔值(True/False):可以直接作为判断条件

这种写法更符合自然语言习惯,比如:

  • “如果有借书”(if 借阅列表)而不是 “如果借阅列表的长度大于 0”
  • “如果可借”(if 可借状态)而不是 “如果可借状态等于真”

熟练后会发现这样写更简洁高效哦~

注:该代码是本人自己所写,可能不够好,不够简便,欢迎大家指出我的不足之处。如果遇见看不懂的地方,可以在评论区打出来,进行讨论,或者联系我。上述内容全是我自己理解的,如果你有别的想法,或者认为我的理解不对,欢迎指出!!!如果可以,可以点一个免费的赞支持一下吗?谢谢各位彦祖亦菲!!!!

http://www.dtcms.com/a/294570.html

相关文章:

  • LLC协议支持哪些类型的帧?它们各自的功能是什么?
  • IAR Embedded Workbench for ARM 8.1 安装教程
  • 深兰科技陈海波:AI企业出海要坚持“区域深耕”与“长期主义”
  • 《设计模式之禅》笔记摘录 - 9.责任链模式
  • 使用Ollama,VLLM,LMDeploy部署大模型
  • 二分查找-162.寻找峰值-力扣(LeetCode)
  • P1040 [NOIP 2003 提高组] 加分二叉树
  • 小米浏览器overflow不能左右滑动
  • spring-cloud概述
  • (Arxiv-2025)OVIS-U1技术报告
  • 想曰加密工具好用吗?本地安全、支持多算法的加密方案详解
  • NTC热敏电阻计算公式
  • 【大模型】Hugging Face常见模型格式详解
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-6,(知识点:二极管,少子多子,扩散/漂移运动)
  • mysql中ROW_NUMBER()、RANK()、DENSE_RANK()用法及区别
  • 在AI深度嵌入企业业务的当下——AI时代的融合数据库
  • 知己知彼:深入剖析跨站脚本(XSS)攻击与防御之道
  • React+Three.js实现3D场景压力/温度/密度分布可视化
  • 使用 piano_transcription_inference将钢琴录音转换为 MIDI
  • 2.4 PNIO-CM
  • 初级网安作业笔记3
  • opencv学习(视频读取)
  • Spring Data Redis 从入门到精通:原理与实战指南
  • 2025暑期—06神经网络-常见网络
  • JVM、Dalvik、ART区别
  • JS逆向实战案例之———x日头条【a-bogus】分析
  • 解析 Chromium 架构分层下 Windows 与 Linux 链接器行为差异及其影响
  • [深度学习] 大模型学习3下-模型训练与微调
  • 提升ARM Cortex-M系统性能的关键技术:TCM技术解析与实战指南
  • C++11扩展 --- 并发支持库(中)