美文网首页
“老奶奶”的python学习笔记(14)

“老奶奶”的python学习笔记(14)

作者: 菁_在路上 | 来源:发表于2019-12-03 12:52 被阅读0次

    知识体系

    第14关:用类与实例的方法编程(实操项目)

    知识点

    明确项目目标

    流浪图书计划:

    鼓励同学们将自己中意的闲置图书贡献出来,形成一个小型的精品图书库,以供同学们免费借阅、流转。

    需要一个图书管理系统,来管理书籍的借阅情况。

    希望这个简易的程序可以做到:查询、添加、借阅、归还图书

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

    1、查询所有书籍

    2、添加书籍

    3、借阅书籍

    4、归还书籍

    5、退出系统

    请输入数字选择对应的功能

    分析过程,拆解项目

    需要定义多少个类?

    每个类有怎样的属性和方法?

    第一种用法是使用类生成实例对象。

    类作为实例对象的模版,每个实例创建后,都将拥有类的所有属性和方法。

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

    回到项目:

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

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

    为了让类的结构更清晰,我们可以将5个功能(查询,添加,借阅,归还,退出系统)选择菜单也封装成一个方法menu(),方便调用其他方法。

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

    class Book:

        def __init__(self):#对实例属性进行初始化

    class BookManager:

        def menu(self):#显示选择菜单,根据不同的选项调用不同的方法

        def show_all_book(self):#显示每本书籍的信息

        def add_book(self):#添加书籍

        def lend_book(self):#借阅书籍

        def return_book(self):#归还书籍

    代码实现,逐步执行

    定义Book类

    根据需求,每本书的基本属性都要有四个:书名、作家、推荐语和借阅状态。

    所以,我们可以利用初始化方法__init__,让实例被创建时自动获得这些属性。

    class Book:

        def __init__(self, name, author, comment, state = 0):

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

            self.name = name

            self.author = author

            self.comment = comment

            self.state = state

    # 分别表示书名、作者、推荐语和借阅状态

    book = Book('看不见的城市','卡尔维诺','献给城市的最后一首爱情诗')

    # state为默认参数,如无修改必要不用传递

    print(book.author)

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

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

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

    状态:未借出

    我们可以在初始化方法的基础上定义一个show_info()方法

    class Book:

        def __init__(self, name, author, comment, state = 0):

            self.name = name

            self.author = author

            self.comment = comment

            self.state = state

        def show_info(self):

            if self.state == 0:

                status = '未借出'

            else:

                status = '已借出'

            return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)

    book1 = Book('像自由一样美丽', '林达', '你要用光明来定义黑暗,用黑暗来定义光明')

    # 传入参数,创建实例

    print(book1.show_info())

    #调用实例方法show_info(),打印出返回值

    还有一个更符合编程习惯的方法__str__(self)

    也能打印出同样的结果。只要在类中定义了__str__(self)方法,那么当使用print打印实例对象的时候,就会直接打印出在这个方法中return的数据。

    class Book:

        def __init__(self, name, author, comment, state = 0):

            self.name = name

            self.author = author

            self.comment = comment

            self.state = state

        def __str__(self):

            if self.state == 0:

                status = '未借出'

            else:

                status = '已借出'

            return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)

    book1 = Book('像自由一样美丽','林达','你要用光明来定义黑暗,用黑暗来定义光明')

    # 传入参数,创建实例对象

    print(book1) # 直接打印对象即可,不能写成print(book1.__str__())

    定义BookManager类

    菜单选项

    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

    查询所有书籍

    1、在类的开头定义一个空列表books,方便其他方法调用,然后把创建的Book实例添加到这个列表里

    class BookManager:

        books = [] # 创建一个列表,列表里每个元素都是Book类的一个实例

    2、创建三个实例对象

    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] # 上面三行代码,可简化为一行,即直接创建列表。这种情况下,可不用在前面创建空列表。

    3、封装成代码

    def show_all_book(self):

        for book in self.books: # self是实例对象的替身

        print(book)

    添加书籍

    def add_book(self):

       new_name = input('请输入书籍名称:')

        new_author = input('请输入作者名称:')

        new_comment = input('请输入书籍推荐语:') # 获取书籍相应信息,赋值给属性

    new_book = Book(new_name, new_author, new_comment) # 传入参数,创建Book类实例

    self.books.append(new_book) # 将new_book添加到列表books里

    print('书籍录入成功!\n')

    借阅书籍

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

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

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

    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 = 1

                    break

            else:

                continue # 如果不满足book.name == borrow_name,则继续循环(这两行可以省略)

    else: print('这本书暂时没有收录在系统里呢')

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

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

    换句话说:将上面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值

    在此基础上,借书代码为:

    def lend_book(self):

        name = input('请输入书籍的名称:')

        res = self.check_book(name)

        if res != None:

            if res.state == 1:

                print('你来晚了一步,这本书已经被借走了噢')

            else:

                print('借阅成功,借了不看会变胖噢~')

                res.state = 1

        else: print('这本书暂时没有收录在系统里呢')

    归还书籍

    在查询图书状态基础上:

    def return_book(self):

        name = input('请输入归还书籍的名称:')

        res = self.check_book(name) # 调用check_book方法,将返回值赋值给变量res

        if res == None: # 如果返回的是空值,即这本书的书名不在系统里

            print('没有这本书噢,你恐怕输错了书名~')

        else: # 如果返回的是实例对象

            if res.state == 0: # 如果实例属性state等于0,即这本书的借阅状态为'未借出'

                print('这本书没有被借走,在等待有缘人的垂青呢!')

            else: # 如果实例属性state等于1,即状态为'已借出'

                print('归还成功!')

                res.state = 0 # 归还后书籍借阅状态为0,重置为'未借出'

    相关文章

      网友评论

          本文标题:“老奶奶”的python学习笔记(14)

          本文链接:https://www.haomeiwen.com/subject/agkcgctx.html