Home > front end >  How to create a list from a .txt file and then convert the list values into objects
How to create a list from a .txt file and then convert the list values into objects

Time:06-21

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.

CodePudding user response:

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

CodePudding user response:

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

    ...

CodePudding user response:

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.

  • Related