0

I am a beginner in Python having trouble with a school project. I'm trying to create a library inventory management system based around a file called books.txt

First of all, here is the raw data of books.txt

Mastering Windows Server 2019 - Second Edition;Krause,Jordan;978-1789804539;005.4476/KRA;5;3;
Windows Server 2019 & PowerShell All In One For Dummies;Perrot,Sara;978-1119560715;005.4476/PER;10;2;
Windows Server Automation with PowerShell Cookbook - Fouth Edition;Lee,Thomas;978-1800568457;005.4476/LEE;3;1;
Python Cookbook: Recipes for Mastering Python 3;Beazley,David;978-1449340377;005.133/BEA;10;8;
Automate the Boring Stuff With Python;Sweigart,Al;978-1593275990;005.133/SWE;10;10;
Head First Python - 2nd Edition;Barry,Paul;978-1491919538;005.133/BAR;4;2;
Python Crash Course - 2nd Edition;Matthes,Eric;978-1593279288;005.133/MAT;12;8;
Python for Dummies;Maruch,Stef;978-0471778646;005.133/MAR;5;0;
Beginning Programming with Python for Dummies;Mueller,John Paul;978-1119457893;005.133/MUE;7;5;
Beginning COBOL for Programmers;Coughlan,Michael;978-1430262534;005.133/COU;1;0;

So what I'm trying to do here is store a list of these book objects in a variable. The aim of the program is to modify the list of book objects, rather than modifying the .txt file directly. After that's all done the user can save the changes and THEN overwrite the .txt file. Anyway, I've tried many different things and right now I feel like this function has got me closest in terms of reading and splitting the lines from the file to create a list.

#Apparently 'with open' stops you from having to close the file.
#Copy of display() for the purposes of playing around.
def inventory3():
    print("\nName \t \t Author \t \t ISBN \t \t Call Number \t \t Stock \t \t Loaned")
    with open("books.txt", "r") as inventoryfile:
        for line in inventoryfile:
            strip_lines=line.strip()
            inventory = strip_lines.split(";")
            print(inventory)

This displays all the lines in the books.txt file correctly (I don't want the square brackets to display, but that's a problem for later) and I know from testing (stuff like test = inventory[-3:]) that it functions correctly as a list. Now the aim is to "index the stored list" to create the book objects, and apparently each book object I create should be stored in a separate list. This was the example I was provided.

books.append(Book(line[0],line[1],line[2],line[3],line[4],line[5]))

And I previously created a book class, like so

class Book:

    def __init__(self, title, author, isbn, callnumber, stock, loaned):
        self.title = title
        self.author = author
        self.isbn = isbn
        self.callnumber = callnumber
        self.stock = stock
        self.loaned = loaned

    def getTitle(self):
        return self.title

    def getAuthor(self):
        return self.author

    def getISBN(self):
        return self.isbn

    def getCallNumber(self):
        return self.callnumber

    def getStock(self):
        return self.stock

    def getLoaned(self):
        return self.loaned

I'm a bit confused on how I'm meant to link these two together. I'm not seeing the progression from getting the contents of the txt file to display to suddenly converting them all into objects (that can then be individually deleted, new books added, etc). I've spent days Googling and YouTubing but found nothing, so I'm here for help. Thank you very much.

3 Answers 3

1

You are almost there! inventory is a list (hence the square brackets).

To create a Book object just update the example you were given to:

books.append(Book(inventory[0],inventory[1],inventory[2],inventory[3],inventory[4],inventory[5]))

To print without the square brackets update your print statement to:

print(' '.join(inventory))
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your answer. When I try to use the books.append line of code you provided, I get a NameError telling me that 'books' is not defined. How do I solve this? I tried changing it to Book.append (referencing the Book class I created) but that gave me an AttributeError (as the Book class has no attribute append, that's clear enough).
Ah, I thought books was already created in the example. You can create an empty list and then add all the books to it: books = [], followed by the line with books.append (make sure to create books before the for-loop). Or you can just create a single book: book = Book(inventory[0],inventory[1],inventory[2],inventory[3],inventory[4],inventory[5])
0

It seems that you want to use the lists created at inventory3 to instantiate your Book class. In this case, you can try to change your function a bit and add a return, like this:

def inventory3():
    inventory = []
    print("\nName \t \t Author \t \t ISBN \t \t Call Number \t \t Stock \t \t Loaned")
    with open("books.txt", "r") as inventoryfile:
        for line in inventoryfile:
            strip_lines=line.strip()
            inventory_line = strip_lines.split(";")[:-1] # Use-1 to get rid of all empty double quotes ('') in the end of each list
            print(inventory_line)
            inventory.append(inventory_line)
    return inventory

With this, you can do:

inventory = inventory3()
books = []
for book_details in inventory:
    books.append(Book(book_details[0],book_details[1], book_details[2],book_details[3],book_details[4],book_details[5]))
print(books)

You'll see your objects created.

And, if you really don't need the empty '' in the and of each list, as i suggested, you can do it with list unpacking, it will be more pythonic. Like this:

inventory = inventory3()
books = []
for book_details in inventory:
    books.append(Book(*book_details))
print(books)

*book_details will be exactly the same as book_details[0],book_details[1], book_details[2],book_details[3],book_details[4],book_details[5].

EDIT

As said in comments, I'm adding an example using dataclasses.

from dataclasses import dataclass

@dataclass
class Book:
    title:str
    author:str
    isbn:str
    callnumber:str
    stock:str
    loaned:str

    # Your Functions

    ...

If you use a dataclass and print your objects you get something that can help you:

Book(title='Mastering Windows Server 2019 - Second Edition', author='Krause,Jordan', isbn='978-1789804539', callnumber='005.4476/KRA', stock='5', loaned='3')

Instead of:

<__main__.Book object at 0x000001F1D23BFFA0>

If you want something defined by yourself, you can implement the repr method of your book class:

class Book:
    def __init__(self, title, author, isbn, callnumber, stock, loaned):
        self.title = title
        self.author = author
        self.isbn = isbn
        self.callnumber = callnumber
        self.stock = stock
        self.loaned = loaned

    def __repr__(self):
        return self.title + '/' + self.author

    # Your Functions

    ...

2 Comments

Awesome, this seems to work well overall, but when I use print(books) it comes out like this - <__main__.Book object at 0x000001200B98E980>, <__main__.Book object at 0x000001200B98E9E0>, etc So the objects are clearly saved, but are not displaying correctly. Do you know why this is?
It's because the default behavior of a class without a repr method implemented is show it's memory location. If you want a pretty print you can implement a repr method in your Book class. If you want something more "professional", i suggest you to use a dataclass, that can help you with some tricky things. I'll edit the answer with an option using dataclasses. If I helped you solving your problem, feel free to upvote and mark as the solution! Thanks! ;D
0

Emmacb's answer above answers your question.

Just to add, you can make use of the @dataclass decorator when creating your Book class. This will reduce the code length, and improve readibility. It is also not neccesary to define the Book.getXXX methods as these could be accessed directly by the attribute names

from dataclasses import dataclass

@dataclass
class Book:
    title: str
    author: str
    isbn: str
    callnumber: str
    stock : str
    loaned : str
    
book_one = Book('Title', 'Author','ISBN', 'Call Number', 'Stock', 'loaned')

book_one_title = book_one.title
print(book_one_title)

This requires you to specify the type of data, which in this example i assumed where all strings.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.