章节十五:项目实操:PK小游戏(3)

目录
  • 章节十五:项目实操:PK小游戏(3)

    • 1. 明确项目目标
    • 2. 分析过程,拆解项目
    • 3. 代码实现,逐步执行
      • 3.1 定义Book类
      • 3.2 类BookManager的编写
        • 3.2.1 选择显示菜单(menu)
        • 3.2.2 显示书籍信息(show_all_book)
        • 3.2.3 添加书籍信息(add_book)
        • 3.2.4 借阅书籍(lend_book)
        • 3.2.5 归还书籍(return_book)
    • 4. 习题练习
      • 4.1 习题一
      • 4.2 习题二

嗨,很开心,又见到你。这一关,是我们第3个项目实操关卡。

希望你能通过这个项目学会用类与实例的方法编写程序,掌握面向对象编程的基本思维,为日后能处理更复杂的代码结构打牢基础。

让我们回顾一下项目实操的三个步骤:

接下来,我们就一步一步推进项目的实现吧。首先是:明确项目目标。

1. 明确项目目标

咳咳,今天我们的任务可是带有浓烈的人文气息——编写一个图书管理系统的程序。先请我们的主人公登场,给我们讲讲他的需求吧。

朋也是大学班上的文娱委员,他留意到周围同学经常表达出希望“课余生活能多看书”的意愿,但苦于不知道要选什么书看。

思前想后,朋也决定启动一个流浪图书计划:鼓励同学们将自己中意的闲置图书贡献出来,形成一个小型的精品图书库,以供同学们免费借阅、流转。

为此他需要一个图书管理系统,来帮助他管理书籍的借阅情况。他希望这个简易的程序可以做到:

好,目标清晰了,看起来并没有超出目前我们的能力范围,接下来让我们一步步把它做出来吧~

确定目标后,下一步是:拆解项目,分析过程。

2. 分析过程,拆解项目

在没接触类之前,如果碰到这样的需求,我们会想到通过定义不同的函数来封装不同的功能。这样当然是可行的,只是可能会多费些功夫。

既然我们今天的主题是类,我们就只用面向对象编程来完成这个程序。

因此,我们要思考:需要定义多少个类?每个类有怎样的属性和方法?

回答之前,我们先来简单总结一下:类的主要用法。

第一种用法是使用类生成实例对象。类作为实例对象的模版,每个实例创建后,都将拥有类的所有属性和方法。

第二种用法是用类将多个函数(方法)打包封装在一起,让类中的方法相互配合。

回到项目:我们的处理对象是每本具体的书,而每本书都有自己的属性信息,所以我们可以定义一个Book类,利用Book类创建一个个书的实例,绑定属性(对应用法1)。

而这个管理系统的运行主体,是多个可供选择的功能的叠加,所以我们可以创建一个系统运行类BookManager,将查询书籍、添加书籍等功能封装成类中的方法以供调用(对应用法2)。

我们的预期效果是当实例化这个系统运行类的时候,会出现一个菜单,能让用户选择不同的功能,如下图所示:

为了让类的结构更清晰,我们可以将这个选择菜单也封装成一个方法menu(),方便调用其他方法。

那么,将上述要编写的两个类整理一下,这个程序的骨架就是这样:(注释里对应每个方法的功能)

接下来,我们可以先按这个框架来编写代码,解决编写过程中出现的每一个问题,让目标得实现。

3. 代码实现,逐步执行

柿子要挑软的捏,我们先来定义Book类。

3.1 定义Book类

根据需求,每本书的基本属性都要有四个:书名、作家、推荐语和借阅状态。所以,我们可以利用初始化方法__init__,让实例被创建时自动获得这些属性。

请你小试牛刀,写出初始化方法的代码,确保后面两行的代码能够顺利执行,打印出作者名卡尔维诺

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = state# 分别表示书名、作者、推荐语和借阅状态  book = Book('看不见的城市','卡尔维诺','献给城市的最后一首爱情诗')
# state为默认参数,如无修改必要不用传递
print(book.author)

为了后续方便参数传递,借阅状态state采用默认参数,用0来表示'未借出',1来表示'已借出'。

初始化方法定义完成后,一旦实例对象被创建,这几个属性就存在且可随时调用。

接下来,我们来看看Book类还需不需要其他方法。

我们注意到系统里有一个功能是显示所有书籍信息,所以我们可以在Book类定义一个方法,当调用这个方法时,就能够打印出这本书的信息,加上循环,就能打印所有书籍的信息。

我们希望的格式是这样的:

名称:《像自由一样美丽》 作者:林达 推荐语:你要用光明来定义黑暗,用黑暗来定义光明。
状态:未借出

那么,我们可以在初始化方法的基础上定义一个show_info()方法,打印出每本书的信息:

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef show_info(self):if self.state == 0:# 如果属性state等于0status = '未借出'# 将字符串'未借出'赋值给statuselse:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s 状态:%s ' % (self.name, self.author, self.comment, status)# 返回书籍信息

我们可以创建一个实例,调用该方法试试看。请你直接运行代码;

Bingo!不过这里我要介绍一个更符合编程习惯的方法__str__(self)

在Python中,如果方法名形式是左右带双下划线的,那么就属于特殊方法(如初始化方法),有着特殊的功能。

解释一下:只要在类中定义了__str__(self)方法,那么当使用print打印实例对象的时候,就会直接打印出在这个方法中return的数据。

可能有点绕,看代码会直观一点。我们直接把上述代码里的方法名show_info(self)替换成__str__(self),留意最后一行调用的代码,然后点击运行:

可见,打印的结果是一模一样的,区别就是__str__打印对象即可打印出该方法中的返回值,而无须再调用方法。

好,Book类的代码我们就完成了,再来瞧一眼~确保你能理解每行代码再继续:

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef __str__(self):if self.state == 0:status = '未借出'else:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)

接下来,我们来看第二个类BookManager。

3.2 类BookManager的编写

回顾一下我们在前面定下的的结构:

menu()是与用户互动的界面,刚刚我们已经给出了demo:

用户输入数字执行相应的功能,程序内部调用的逻辑应该是:

1.查询所有书籍
# 调用方法show_all_book()2.添加书籍
# 调用方法add_book()3.借阅书籍
# 调用方法lend_book()4.归还书籍
# 调用方法return_book()5.退出系统请输入数字选择对应的功能:

3.2.1 选择显示菜单(menu)

显然,这里需要用到多层条件判断语句。相信这对你来说并不难,所以下面直接给出示例:

class BookManager:def menu(self):print('欢迎使用流浪图书管理系统,每本沉默的好书都是一座流浪的岛屿,希望你有缘发现并着陆,为精神家园找到一片栖息地。\n')while True:print('1.查询所有书籍\n2.添加书籍\n3.借阅书籍\n4.归还书籍\n5.退出系统\n')choice = int(input('请输入数字选择对应的功能:'))if choice == 1:self.show_all_book()# 调用对象方法时self不能忘elif choice == 2:self.add_book()elif choice == 3:self.lend_book()elif choice == 4:self.return_book()elif choice == 5:print('感谢使用!愿你我成为爱书之人,在茫茫书海里相遇。')break

那么我们就完成了menu()的定义,但目前还不能运行,是因为代码里的许多方法我们还没有定义,接下来我们就来一个个攻克。

3.2.2 显示书籍信息(show_all_book)

先来看看show_all_book()方法,它的功能是打印出系统里所有书籍的信息。

为了方便调试,验证代码是否写对了,我们可以先往书籍系统里添加几本书籍,也就是创建Book类的实例对象。

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef __str__(self):if self.state == 0:status = '未借出'else:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)class BookManager:def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。', 1)manager = BookManager()

上面的代码,在BookManager类的初始化方法中创建了3个Book类的实例对象。换言之,当创建实例manager时,book1、book2、book3就会生成。

当有多个对象的时候,就要考虑数据存储的方式。由于每个Book实例是并列平行的关系,所以可以用列表来存储。

于是可以在类的开头定义一个空列表books,方便其他方法调用,然后把刚刚创建的Book实例添加到这个列表里。看代码:

class BookManager:books = []# 创建一个列表,列表里每个元素都是Book类的一个实例def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。', 1)# 创建三个实例对象self.books.append(book1)self.books.append(book2)self.books.append(book3)# 往列表依次添加元素,注意调用类属性books时,self不能丢# self.books = [book1, book2, book3]# 上面三行代码,可简化为一行,即直接创建列表。这种情况下,可不用在前面创建空列表。

如此一来,列表books里的每个元素都是基于Book类创建的实例对象,所以每个元素会自动拥有Book类的方法__str__。我们可以验证一下:

# 阅读最后三行代码,直接运行即可
class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef __str__(self):status = '未借出'if self.state == 1:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)class BookManager:books = []# 存储书籍的列表,每一个元素都是Book的实例对象def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。',1)self.books.append(book1)self.books.append(book2)self.books.append(book3)manager = BookManager()
print(len(manager.books))
# 打印列表长度
for book in manager.books:print(book)

验证成功。book1,book2,book3,都是Book类的实例对象。又因为对象本身有__str__方法,所以当打印对象时,就会打印出该方法中的返回值。

发现了吗?这个结果和我们想要定义的显示书籍信息的方法show_all_book()是一样的,所以我们可以把最后几行代码封装成方法。

class BookManager:books = []def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。',1)self.books.append(book1)self.books.append(book2)self.books.append(book3)def menu(self):print('欢迎使用流浪图书管理系统,每本沉默的好书都是一座流浪的岛屿,希望你有缘发现并着陆,为精神家园找到一片栖息地。\n')while True:print('1.查询所有书籍\n2.添加书籍\n3.借出书籍\n4.归还书籍\n5.退出系统\n')choice = int(input('请输入数字选择对应的功能:'))if choice == 1:self.show_all_book()def show_all_book(self):for book in self.books:# self是实例对象的替身print(book)manager = BookManager()
manager.menu()

我们将两个类的代码组合在一起,直接运行,遇到输入请输入数字1:

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef __str__(self):status = '未借出'if self.state == 1:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)class BookManager:books = []def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。',1)self.books.append(book1)self.books.append(book2)self.books.append(book3)def menu(self):print('欢迎使用流浪图书管理系统,每本沉默的好书都是一座流浪的岛屿,希望你有缘发现并着陆,为精神家园找到一片栖息地。\n')while True:print('1.查询所有书籍\n2.添加书籍\n3.借出书籍\n4.归还书籍\n5.退出系统\n')choice = int(input('请输入数字选择对应的功能:'))if choice == 1:self.show_all_book()breakdef show_all_book(self):for book in self.books:print(book)print('')manager = BookManager()
manager.menu()

3.2.3 添加书籍信息(add_book)

完美!那么打印书籍信息的方法我们就讲到这。接下来我们来看第二个功能:添加书籍add_book()

代码结构应该是这样的:当输入数字2的时候,就会跳转到对应的方法:

class Book:   def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = stateclass BookManager:books = [] def add_book(self):new_name = input('请输入书籍名称:')new_author =  input('请输入作者名称:')new_comment = input('请输入书籍推荐语:')# 获取书籍相应信息,赋值给属性new_book = Book(new_name, new_author, new_comment)# 传入参数,创建Book类实例new_book self.books.append(new_book)# 将new_book添加到列表books里print('书籍录入成功!\n')manager = BookManager()
manager.add_book()

如果注释没有看懂,可以结合下面的数据流转图再理解一下:

好了,已经triple kill了!做得好!

3.2.4 借阅书籍(lend_book)

接下来,来看第三个功能:借阅书籍lend_book()。这是最关键的一环,也是最容易出错的一环。所以,要集中注意力哦。

同样,我们把之前写好的代码整合在一起。虽然代码会越来越长,但都是你已经掌握了的,莫慌!一个函数一个函数看就好了。

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef __str__(self):status = '未借出'if self.state == 1:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)class BookManager:books = []def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。',1)self.books.append(book1)self.books.append(book2)self.books.append(book3)def menu(self):print('欢迎使用流浪图书管理系统,每本沉默的好书都是一座流浪的岛屿,希望你有缘发现并着陆,为精神家园找到一片栖息地。\n')while True:print('1.查询所有书籍\n2.添加书籍\n3.借阅书籍\n4.归还书籍\n5.退出系统\n')choice = int(input('请输入数字选择对应的功能:'))if choice == 1:self.show_all_book()# self是实例对象的替身elif choice == 2:self.add_book()elif choice == 3:self.lend_book()def show_all_book(self):for book in self.books:print(book)def add_book(self):new_name = input('请输入书籍名称:')new_author =  input('请输入作者名称:')new_comment = input('请输入书籍推荐语:')new_book = Book(new_name, new_author, new_comment)self.books.append(new_book)print('书籍录入成功!\n')def lend_book(self):

现在,想一想:借阅功能lend_book()要怎么实现呢?可以先想想我们平时找人借东西,会出现哪几种情况?

应该逃不出这几种:1.TA压根没这个东西;2.TA有这个东西,但是被借走了;3.TA有这个东西,借给我们了;4. TA不想借给我们。

在这个项目里,第四种情况可以忽略不计。所以,整理一下思路:

这里有两个要点:1. 怎么判断这本书在不在系统里;2.怎么判断这本书有没有被借走。

请你动动脑筋想想用代码要怎么判断,想好再继续点击,查看答案。

首先,判断在不在系统里,我们可以采用遍历书籍列表books的方式,一旦输入的书籍名称和列表元素中的书籍名称出现匹配,就证明系统里有这本书。

其次,如果书在系统里,有没有被借走可以根据实例属性state来判断,0表示'未借出',1表示'已借出'。

下面我会给出这两个判断的代码,请你结合注释理解代码的逻辑:

class BookManager:books = []     def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。',1)self.books.append(book1)self.books.append(book2)self.books.append(book3)def lend_book(self):borrow_name = input('请输入你想借阅的书籍名称:')for book in self.books:# 遍历列表,此时books有三个元素,即book1,book2,book3三个实例if book.name == borrow_name:# 如果列表中有实例的属性name和输入的书籍名称相等if book.state == 1:# 借阅状态为'已借出'print('你来晚一步,这本书已经被借走了噢')break# 一旦有对象满足条件,则退出for循环else:# 借阅状态为'未借出'print('借阅成功!借了不看会变胖噢~')book.state = 1breakelse:continue# 如果不满足book.name == borrow_name,则继续循环(这两行可以省略)  else:print('这本书暂时没有收录在系统里呢')

注意这里有几个层级的else语句,我们可以看到最外层结构是for...else,表示的是当for循环里的对象都遍历完毕后,才执行else子句的内容。

也就是说,当列表里没有对象能够满足if book.name == borrow_name条件时,才会打印else子句的那一句话。(如果for循环内部有break子句,也不会执行)

代码是完成了,但归还书籍的时候,也会碰到类似的逻辑。为了不写重复的代码,我们可以额外在类中定义一个方法,专门检查输入的书名是否在书籍列表里。

换句话说:将上面lend_book()方法中检测书名的代码抽出来,封装成一个函数。这样就可以在借书和还书的代码里直接调用,不用两处重复写同样的代码。

下面,我们来看下这个方法要怎么写:

class BookManager:  books = []name = input('请输入书籍名称:')def check_book(self, name):for book in self.books:# 遍历列表的每个元素,即每个Book实例if book.name == name:# 如果存在有实例名称与输入书籍名称是一样的return book # 返回该实例对象,遇到return语句方法停止执行  else:# 若for循环中,没有返回满足条件的对象,则执行else子句 return None# 返回None值

为什么要分别返回书籍名称和None值呢?相信你读完下面的代码,就可以理解了。

class BookManager:books = []     def check_book(self,name):for book in self.books:if book.name == name:return book   else:return Nonedef lend_book(self):name = input('请输入书籍的名称:')res = self.check_book(name)# 将name作为参数调用check_book方法,并将返回值赋值给变量resif res != None:# 如果返回值不等于None值,即返回的是实例对象if res.state == 1:# 如果实例对象的属性state为1,即借阅状态为已租借print('你来晚了一步,这本书已经被借走了噢')else:# 如果state为0print('借阅成功,借了不看会变胖噢~')res.state = 1# 书籍借出后属性state变为1else:# 如果返回值为None值print('这本书暂时没有收录在系统里呢')

呼~是不是优雅很多?我们将目前为止的代码,整合在一起,就是:

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef __str__(self):status = '未借出'if self.state == 1:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)class BookManager:#存储书籍的列表,每一个元素都是Book的实例对象books = []def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。',1)self.books.append(book1)self.books.append(book2)self.books.append(book3)def menu(self):print('欢迎使用流浪图书管理系统,每本沉默的好书都是一座流浪的岛屿,希望你有缘发现并着陆,为精神家园找到一片栖息地。\n')while True:print('1.查询所有书籍\n2.添加书籍\n3.借出书籍\n4.归还书籍\n5.退出系统\n')choice = int(input('请输入数字选择对应的功能:'))if choice == 1:self.show_all_book()elif choice == 2:self.add_book()elif choice == 3:self.lend_book()elif choice == 4:self.return_book()elif choice == 5:print('感谢使用!')breakdef show_all_book(self):for book in self.books:print(book)print('')def add_book(self):new_name = input('请输入书籍名称:')new_author =  input('请输入作者名称:')new_comment = input('请输入书籍推荐语:')new_book = Book(new_name, new_author, new_comment)self.books.append(new_book)print('书籍录入成功!\n')def check_book(self,name):for book in self.books:if book.name == name:return book else:return Nonedef lend_book(self):name = input('请输入书籍的名称:')res = self.check_book(name)if res != None:if res.state == 1:print('你来晚了一步,这本书已经被借走了噢')else:print('借阅成功,借了不看会变胖噢~')res.state = 1else:print('这本书暂时没有收录在系统里呢')manager = BookManager()
manager.menu()

将近80行,多不容易呀!请确保你能读懂以上每一行代码,再继续往下冲刺~

3.2.5 归还书籍(return_book)

现在只剩下归还图书return_book这一功能了,它和lend_book有着异曲同工之妙,也是调用check_book方法进行判断。

如果你想尝试一下的话,可以补充完整以下return_book(self)的相关语句。

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef __str__(self):status = '未借出'if self.state == 1:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)class BookManager:books = []def __init__(self):book1 = Book('惶然录','费尔南多·佩索阿','一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')book2 = Book('以箭为翅','简媜','调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')book3 = Book('心是孤独的猎手','卡森·麦卡勒斯','我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。',1)self.books.append(book1)self.books.append(book2)self.books.append(book3)def menu(self):print('欢迎使用流浪图书管理系统,每本沉默的好书都是一座流浪的岛屿,希望你有缘发现并着陆,为精神家园找到一片栖息地。\n')while True:print('1.查询所有书籍\n2.添加书籍\n3.借阅书籍\n4.归还书籍\n5.退出系统\n')choice = int(input('请输入数字选择对应的功能:'))if choice == 1:self.show_all_book()elif choice == 2:self.add_book()elif choice == 3:self.lend_book()elif choice == 4:self.return_book()elif choice == 5:print('感谢使用!愿你我成为爱书之人,在茫茫书海里相遇。')breakdef show_all_book(self):print('书籍信息如下:')for book in self.books:print(book)print('')def add_book(self):new_name = input('请输入书籍名称:')new_author =  input('请输入作者名称:')new_comment = input('请输入书籍推荐语:')new_book = Book(new_name, new_author, new_comment)self.books.append(new_book)print('书籍录入成功!\n')def check_book(self,name):for book in self.books:if book.name == name:return book else:return Nonedef lend_book(self):name = input('请输入书籍的名称:')res = self.check_book(name)if res != None:if res.state == 1:print('你来晚了一步,这本书已经被借走了噢')else:print('借阅成功,借了不看会变胖噢~')res.state = 1else:print('这本书暂时没有收录在系统里呢')def return_book(self):name = input('请输入归还书籍的名称:')res = self.check_book(name)# 调用check_book方法,将返回值赋值给变量resif res == None:# 如果返回的是空值,即这本书的书名不在系统里print('没有这本书噢,你恐怕输错了书名~')else:# 如果返回的是实例对象if res.state == 0:# 如果实例属性state等于0,即这本书的借阅状态为'未借出'print('这本书没有被借走,在等待有缘人的垂青呢!')else:# 如果实例属性state等于1,即状态为'已借出'print('归还成功!')res.state = 0# 归还后书籍借阅状态为0,重置为'未借出'manager = BookManager()
manager.menu()

现在,大功告成,享受胜利果实的时刻到了~请你愉快地玩下辛辛苦苦写出来的小程序吧。

4. 习题练习

4.1 习题一

1.练习介绍
利用类的继承,创建一个Book类的子类。

2.练习要求
在Book类的基础上,创建一个子类FictionBook类表示虚构类图书,并改造初始化方法,增加一个默认参数type = '虚构类'
再利用str()方法打印出FictionBook类实例的相关信息。

3.书写代码
1)请你在下侧代码的基础上,创建一个子类FictionBook
2)在子类改造父类的初始化方法,让程序能够打印出实例book的相关信息。

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = state# 创建一个Book类的子类 FictionBookclass FictionBook(Book):def __init__(self, name, author, comment, state = 0, type = '虚构类'):Book.__init__(self, name, author, comment, state = 0)self.type = typedef __str__(self):status = '未借出'if self.state == 1:status = '已借出'return '类型:%s \n名称:《%s》 \n作者:%s \n推荐语:%s\n状态:%s ' % (self.type, self.name, self.author, self.comment, status)book = FictionBook('囚鸟','冯内古特','我们都是受困于时代的囚鸟')
print(book)

4.2 习题二

1.练习介绍
在原有代码的基础上做一些优化,让用户输入作者名,就能打印出系统里该作者所有书籍的相关信息。

2.练习要求
新建一个类的方法,让程序能够根据作者名来展示相关书籍的信息。

3.书写代码
请你阅读代码,在此基础上,补充show_author_book()相关代码,实现根据作者名打印相关书籍信息的功能。
因为代码已经创建好了3个Book实例,代码运行后预期实现效果:

输入'三毛',系统就会打印出两本书的相关信息。
输入'毛姆',系统就会打印出一本书的相关信息。
输入'二毛', 系统就会打印出'很可惜,我们暂时没有收录这位作者的作品'

class Book:def __init__(self, name, author, comment, state = 0):self.name = nameself.author = authorself.comment = commentself.state = statedef __str__(self):status = '未借出'if self.state == 1:status = '已借出'return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)class BookManager:authors = []def __init__(self):book1 = Book('撒哈拉的故事','三毛','我每想你一次,天上便落下一粒沙,从此便有了撒哈拉。')book2 = Book('梦里花落知多少','三毛','人人都曾拥有荷西,虽然他终会离去。')book3 = Book('月亮与六便士','毛姆','满地都是六便士,他却抬头看见了月亮。')self.books = [book1,book2,book3]self.authors.append(book1.author)self.authors.append(book2.author)self.authors.append(book3.author)def menu(self):while True:print('1.查询书籍')choice = int(input('请输入数字选择对应的功能:'))if choice == 1:self.show_author_book()else:print('感谢使用!')breakdef show_author_book(self):author = input('请输入想查询作家的名称:')if author in self.authors:print(author + '的作品有:')for book in self.books:if book.author == author:print(book)else:print('很可惜,我们暂时没有收录这位作者的作品')manager = BookManager()
manager.menu()

章节十五:项目实操:PK小游戏(3)相关推荐

  1. 【嵌入式Linux驱动开发】十五、实操Linux开发中的中断,编写第一个按键驱动程序

       慷慨歌燕市,从容作楚囚.   引刀成一快,不负少年头. 文章目录 一.实验目标与原理图分析 二.编写程序 2.1 修改.编译.覆盖设备树文件 2.1.1 添加 pinctrl 节点 2.1.2 ...

  2. Python17_项目实操关卡-人机PK

    项目实操关卡-人机PK 通过实战去成长,这体现在:能在学习初期就知道什么是关键知识,了解专业程序员一般是怎么思考和解决问题的,在一遍遍分析问题.拆解问题及解决问题的过程中真正地理解知识,并用这些知识来 ...

  3. RabbitMQ第五个实操小案例——主题交换机(TopicExchange)

    文章目录 RabbitMQ第五个实操小案例--主题交换机(TopicExchange) RabbitMQ第五个实操小案例--主题交换机(TopicExchange) TopicExchange 和 D ...

  4. 【Python自查手册】之项目实操

    项目实操步骤 分析:明确项目目标 拆解(将一个问题拆解为多个步骤或者多种不同的层次,逐步解决和执行并最终达到效果)–分析过程拆到无法拆解为止 解决:代码实现,逐步执行 三局两胜制小游戏 # 敌我两PK ...

  5. python 爬虫(项目实操)

    用BeautifulSoup库解析数据和提取数据,解析数据的方法是: 提取数据的方法是用find() 与find_all() 最后,我们把事情串起来,就变成下图中的模样.它所对应的,正是爬虫四步中的前 ...

  6. 本地房产公众号项目实操分享

    ​本地房产公众号项目实操分享 房地产公众号,可以每天更新最新楼盘资讯.楼市预判.土拍信息等,文章可以不用全部原创,那我们可以从哪些地方寻找素材呢? 1.安居客;2.本地土拍网;3.本地规划网;4.房天 ...

  7. 实操-微信小程序渲染html内容

    实操-微信小程序渲染html内容 在小程序中渲染html内容--wxParse 下载 wxParse 组件并配置到项目当中 使用 wxParse 1.在 js文件中引入 2.在wxml中使用 保存一下 ...

  8. SpringBoot集成Mybatis项目实操

    本文为<从零打造项目>系列第三篇文章,首发于个人网站. <从零打造项目>系列文章 比MyBatis Generator更强大的代码生成器 SpringBoot项目基础设施搭建 ...

  9. 新项目实操分析,用付费视频进行流量变现

    我们知道,互联网的发展,使得网民越来越多,不仅上网的用户在增多,上网的时间也逐年增加. 所以很多人都想做互联网的生意,因为互联网有足够的关注度和巨大的流量.而且,互联网项目属于网上创业,硬件门槛相对较 ...

最新文章

  1. Matplotlib实例教程(二)饼状图
  2. quick-cocos2d-x api构建文档
  3. anchor free 目标检测_《目标检测》系列之二:目标检测中的Anchor机制回顾
  4. java代码隐藏面消除算法,java常面的几种排序算法
  5. 马斯克非常有信心:SpaceX将在2026年前让人类登陆火星
  6. pandas基础实例
  7. 我的世界服务器为什么显示崩溃,我的世界服务器崩溃的指令 | 手游网游页游攻略大全...
  8. android imagebutton的点击事件,Android 点击ImageButton时有“按下”的效果的实现
  9. 《炬丰科技-半导体工艺》--技术资料合集14
  10. pink老师世纪佳缘作业
  11. RAIN - SEKAI NO OWARI - 歌词翻译及罗马音译整理
  12. Vue组件的抽离和封装
  13. 在unity打开c#脚本写代码没有Unity相关提示
  14. 局部线性嵌入(Locally Linear Embedding,简称LLE)
  15. bem css_CSS体系结构:块元素修饰符(BEM)和原子CSS
  16. tcpdump抓取网络
  17. 3D渲染技术分享:3D游戏开发渲染调试高级技巧
  18. setTimeout with a shorter delay
  19. Android中添加和识别手势操作
  20. Git工具常用命令详解

热门文章

  1. bash shell 命令 - linux
  2. 有的工业互联网重于泰山,有的工业互联网轻于鸿毛
  3. Android开发 设置手机壁纸
  4. 《卸甲笔记》-单行函数对比之二
  5. unity 鼠标放置 ui_ui层次结构以及不常见但至关重要的任务放置在哪里
  6. 7月14日第壹简报,星期四,农历六月十六
  7. 【1000套HTML5+CSS项目实战案例】大学生期末网页作业源代码
  8. Shader学习之Cg语言三(Cg表达式与控制语句)
  9. matlab用抛物线族表示马鞍面,matlab画马鞍面
  10. Linux I2C 设备注册