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.