[Basic knowledge of python] 14. Construction of library management system (practical operation of classes and objects)

Preface

Through this project, I hope you can learn to write programs using class and instance methods, master the basic thinking of object-oriented programming, and lay a solid foundation for handling more complex code structures in the future.

I once mentioned to you that learning Python will make the fastest progress by doing projects. What I didn’t say is: you will always encounter various difficulties when doing projects, unreasonable logic, and code that frequently reports errors.

Therefore, if you encounter confusion or obstacles during today's practical operation, you can stop and let yourself focus on thinking and confirm that your understanding is correct before continuing. There is no need to rush for success.

After all, we're not in a hurry. My biggest hope is that you can eat what you have learned, digest it at your own pace, and turn it into nutrients that truly belong to you.

Of course, if you can get through it all in one go, that’s great too! Anyway, let me cheer you up first.

Okay, let’s review the three steps of project implementation:

Insert image description here
Next, let’s promote the implementation of the project step by step. The first is: clarify the project goals.

Clarify project goals

Ahem, today our task has a strong humanistic flavor - writing a program for a library management system. Let’s first invite our protagonist to appear and tell us about his needs.

Peng was also an entertainment committee member in his college class. He noticed that his classmates often expressed the wish to "read more books in their spare time", but he struggled with not knowing what books to choose.

After thinking about it, Peng Ye decided to launch a homeless book project: encouraging students to contribute their favorite idle books to form a small library of high-quality books for students to borrow and circulate for free.

For this reason, he needs a library management system to help him manage the borrowing of books. He hopes that this simple program can do:
Insert image description here
Okay, the goal is clear, and it doesn’t seem to be beyond our current capabilities. Let’s build it step by step~

After determining the goals, the next step is to dismantle the project and analyze the process.

Analyze the process and dismantle the project

Before we came into contact with classes, if we encountered such a need, we would think of encapsulating different functions by defining different functions. This is of course feasible, but it may take a little more effort. The teacher recommends that you try it after class.

Since our topic today is classes, we will use only object-oriented programming to complete this program.

Therefore, we have to think: How many classes need to be defined? What properties and methods does each class have?

Before answering, let’s briefly summarize: the main uses of classes.
Insert image description here
The first usage is to use a class to generate instance objects. A class serves as a template for instance objects. After each instance is created, it will have all the properties and methods of the class.

The second usage is to use a class to package multiple functions (methods) together so that the methods in the class can cooperate with each other.

Back to the project: Our processing object is each specific book, and each book has its own attribute information, so we can define a Book class, use the Book class to create individual book instances, and bind attributes (for application Method 1).

The running body of this management system is the superposition of multiple optional functions, so we can create a system running class BookManager to encapsulate functions such as querying books and adding books into methods in the class for calling (for application methods 2).

Our expected effect is that when instantiating this system running class, a menu will appear that allows the user to select different functions, as shown in the figure below: In order to make the structure of the class clearer, we can also
Insert image description here
encapsulate this selection menu into A method menu() to facilitate calling other methods.

Then, sort out the two classes to be written above. The skeleton of this program is like this: (The comments correspond to the functions of each method)
Insert image description here
Next, we can first write the code according to this framework to solve every problem that occurs during the writing process. A question to achieve the goal.

Code implementation, step by step execution

We have to pick the soft persimmon. Let’s define the Book class first.

Define Book class

According to requirements, each book must have four basic attributes: title, author, recommendation and borrowing status. Therefore, we can use the initialization method __init__ to automatically obtain these attributes when the instance is created.

Please give it a try, write the code of the initialization method, ensure that the next two lines of code can be executed smoothly, and print out the author's name Calvino.

Reference Code:

class Book:
    def __init__(self, name, author, comment, state = 0):
        self.name = name
        self.author = author
        self.comment = comment
        self.state = state
      # 分别表示书名、作者、推荐语和借阅状态  

book = Book('看不见的城市','卡尔维诺','献给城市的最后一首爱情诗')
# state为默认参数,如无修改必要不用传递
print(book.author)

In order to facilitate parameter transfer in the future, the borrowing status state uses default parameters, using 0 to represent 'not borrowed' and 1 to represent 'borrowed'.

After the initialization method is defined, once the instance object is created, these properties exist and can be called at any time.

Next, let's see if the Book class needs any other methods.

We noticed that there is a function in the system to display all book information, so we can define a method in the Book class. When this method is called, the information of this book can be printed. With the addition of a loop, the information of all books can be printed. information.

The format we want is this:

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

Then, we can define a show_info() method based on the initialization method to print out the information of each book:

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:
        # 如果属性state等于0
            status = '未借出'
            # 将字符串'未借出'赋值给status
        else:
            status = '已借出'
        return '名称:《%s》 作者:%s 推荐语:%s 状态:%s ' % (self.name, self.author, self.comment, status)
        # 返回书籍信息

We can create an instance and call this method to try it out. Please run the code directly;

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(),打印出返回值

operation result:

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

Bingo! However, the teacher here wants to introduce a method __str__(self) that is more in line with programming habits.

In Python, if the method name has double underscores on the left and right, it is a special method (such as an initialization method) and has special functions.

Explain: As long as the __str__(self) method is defined in the class, when you use print to print the instance object, the data returned in this method will be printed directly.

It may be a bit convoluted, but it will be more intuitive if you look at the code. We directly replace the method name show_info(self) in the above code with __str__(self), pay attention to the last line of code called, and then click Run:

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__())

operation result:

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

It can be seen that the printed results are exactly the same. The difference is that the __str__ print object can print out the return value in the method without calling the method again.

Okay, we have completed the code for the Book class. Let’s take another look at it and make sure you understand each line of code before continuing:

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)

Next, let's look at the second class BookManager.

Writing class BookManager

Let’s review the structure we decided earlier:
Insert image description here

User menu menu()

menu() is an interface for interacting with users. We have just given a demo:
Insert image description here
the user enters numbers to execute the corresponding function. The logic called within the program should be:

1.查询所有书籍
# 调用方法show_all_book()

2.添加书籍
# 调用方法add_book()

3.借阅书籍
# 调用方法lend_book()

4.归还书籍
# 调用方法return_book()

5.退出系统

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

Obviously, multi-level conditional judgment statements need to be used here. I believe this is not difficult for you, so here is an example:

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

Then we have completed the definition of menu(), but it cannot be run yet because we have not defined many methods in the code. Next, we will overcome them one by one.

View all books show_all_book()

Let's take a look at the show_all_book() method first. Its function is to print out information about all books in the system.

In order to facilitate debugging and verify whether the code is written correctly, we can first add a few books to the book system, that is, create an instance object of the Book class.

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)

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

manager = BookManager()

The above code creates three instance objects of the Book class in the initialization method of the BookManager class. In other words, when the instance manager is created, book1, book2, and book3 will be generated.

When there are multiple objects, you need to consider the way the data is stored. Since each Book instance is in a parallel relationship, it can be stored in a list.

So you can define an empty list books at the beginning of the class to facilitate other method calls, and then add the Book instance just created to this list. Look at the code:

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

In this way, each element in the list books is an instance object created based on the Book class, so each element will automatically have the method __str__ of the Book class. We can verify it:

# 阅读最后三行代码,直接运行即可
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):
        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)

operation result:

3
名称:《惶然录》 作者:费尔南多·佩索阿 推荐语:一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。
状态:未借出 
名称:《以箭为翅》 作者:简媜 推荐语:调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。
状态:未借出 
名称:《心是孤独的猎手》 作者:卡森·麦卡勒斯 推荐语:我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。
状态:已借出 

Verification successful. book1, book2, and book3 are all instance objects of the Book class. And because the object itself has the __str__ method, when the object is printed, the return value in the method will be printed.

Found it? This result is the same as the method show_all_book() we want to define to display book information, so we can encapsulate the last few lines of code into methods.

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()

We combine the codes of the two classes and run them directly. When encountering input, please enter the number 1:

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):
        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()
                break

    def show_all_book(self):
        for book in self.books:
            print(book)
            print('')

manager = BookManager()
manager.menu()

operation result:

欢迎使用流浪图书管理系统,每本沉默的好书都是一座流浪的岛屿,希望你有缘发现并着陆,为精神家园找到一片栖息地。

1.查询所有书籍
2.添加书籍
3.借出书籍
4.归还书籍
5.退出系统

请输入数字选择对应的功能:1
名称:《惶然录》 作者:费尔南多·佩索阿 推荐语:一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。
状态:未借出 

名称:《以箭为翅》 作者:简媜 推荐语:调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。
状态:未借出 

名称:《心是孤独的猎手》 作者:卡森·麦卡勒斯 推荐语:我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。
状态:已借出 

Perfect! So that’s it for us to talk about the method of printing book information. Next let's look at the second function: add books add_book().

Add books add_book()

The code structure should be like this: when the number 2 is entered, it will jump to the corresponding method:

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()

    def show_all_book(self):
        for book in self.books:
            print(book)
    
    def add_book(self):
        # 添加书籍

manager = BookManager()
manager.menu()

I guess it's time to give you a chance to practice. Please add the add_book(self) code based on the above code, try to enter a book you like, and then jump back to the query function to see if it runs successfully.

Reference code: (For the convenience of reading, only relevant codes are given)

class Book:   

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

class 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()

If you don’t understand the comments, you can combine it with the data flow diagram below to understand it:
Insert image description here
Okay, triple kill has been done! well done!

Next, let’s look at the third function: lending books lend_book().

Lend books lend_book()

This is the most critical link and also the most error-prone link. So, stay focused.

Again, we integrate the code we wrote previously. Although the code will get longer and longer, you have already mastered it, so don’t panic! Just look at it function by function.

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):
        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):

Now, think about it: how to implement the lending function lend_book()? We can first think about what situations we usually encounter when we ask someone to borrow something.

There should be no escape from the following: 1. He doesn’t have this thing at all; 2. He has this thing, but it was borrowed; 3. He has this thing and lent it to us; 4. He doesn’t want to lend it to us.

In this project, the fourth situation can be ignored. So, let’s sort out our thoughts:

Insert image description here
There are two key points here: 1. How to determine whether the book is in the system; 2. How to determine whether the book has been borrowed.

Please use your brain to think about how to use the code to judge, and then continue to check the answer.

First, to determine whether it is in the system, we can traverse the book list books. Once the entered book name matches the book name in the list element, it is proved that the book exists in the system.

Secondly, if the book is in the system, whether it has been borrowed can be judged based on the instance attribute state. 0 means 'not borrowed' and 1 means 'borrowed'.

I will give the code for these two judgments below. Please combine the comments to understand the logic of the code:

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 = 1
                    break
            else:
                continue
          # 如果不满足book.name == borrow_name,则继续循环(这两行可以省略)  
        else:
            print('这本书暂时没有收录在系统里呢')

Note that there are several levels of else statements here. We can see that the outermost structure is for...else, which means that the content of the else clause is executed only after all the objects in the for loop have been traversed.

That is to say, when there is no object in the list that satisfies the condition of if book.name == borrow_name, the sentence of the else clause will be printed. (If there is a break clause inside the for loop, it will not be executed)

The code is completed, but when returning the books, you will encounter similar logic. In order not to write repeated code, we can define an additional method in the class to specifically check whether the entered book title is in the book list.

In other words: Extract the code for detecting book titles in the above lend_book() method and encapsulate it into a function. In this way, you can call it directly in the code for borrowing and returning books, without having to write the same code twice.

Next, let’s take a look at how to write this method:

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值

Why do we need to return the book name and None value respectively? I believe you will understand it after reading the code below.

class BookManager:

    books = []     

    def check_book(self,name):
        for book in self.books:
            if book.name == name:
                 return book   
        else:
            return None

    def lend_book(self):
        name = input('请输入书籍的名称:')
        res = self.check_book(name)
        # 将name作为参数调用check_book方法,并将返回值赋值给变量res

        if res != None:
        # 如果返回值不等于None值,即返回的是实例对象
            if res.state == 1:
            # 如果实例对象的属性state为1,即借阅状态为已租借
                print('你来晚了一步,这本书已经被借走了噢')
            else:
            # 如果state为0
                print('借阅成功,借了不看会变胖噢~')
                res.state = 1
                # 书籍借出后属性state变为1
        else:
        # 如果返回值为None值
            print('这本书暂时没有收录在系统里呢')

Huh~ isn’t it much more elegant? Let's put the code together so far:

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):
        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('感谢使用!')
                break
 
    def 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 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('这本书暂时没有收录在系统里呢')
 
manager = BookManager()
manager.menu()

Nearly 80 lines, how difficult it is! Please make sure you can understand each line of code above before continuing to sprint~

Now only the function of return_book is left, which is similar to lend_book and also calls the check_book method for judgment.

If you want to try it, you can add the complete return_book(self) related statements, or check the reference code directly.

Reference code: (focus on how the return_book method is written)

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):
        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('感谢使用!愿你我成为爱书之人,在茫茫书海里相遇。')
                break
 
    def 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 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,重置为'未借出'
 
manager = BookManager()
manager.menu()

Now, you're done, it's time to enjoy the fruits of victory~ Please happily play with the small program you worked so hard to write.

The above is the entire content of this project. I hope you can understand from this project how to use "classes" to write programs and solve problems.

If you have difficulty learning, don't be discouraged. After all, the concepts of classes and objects are indeed not easy to understand for beginners. Practice more and think more, and I believe you will have a moment of enlightenment.

Of course, there is still room for improvement in this program, such as classifying books, entering the name of the borrower, setting the return deadline, etc...

In addition, you will find that currently our code can only be run in the terminal window and has no impact or trace on the world outside the terminal.

This is because we have not yet learned file reading and writing in Python, so we cannot use Python to create, read, and save files on the hard disk yet.

When we learn module-related knowledge, we can also encapsulate the code into a program that has a graphical interface and database management and can be run outside the terminal, just like various software on your computer.

And these are what we will learn next.

Guess you like

Origin blog.csdn.net/qq_41308872/article/details/132294946