Ivan Lesiv
Ivan Lesiv

Reputation: 59

How do I get the return value of my __str__() function to print in my main?

I need to create two classes for a program that takes in input variable for a book, title, author, number of pages and looks to see if it's checked out and then adds books to a dictionary in the following format dictionary[title] = author. Then I need to print al of my information in a main function in this format: ""title author pages checkedOut." I basically need to print out the return value of my __str__() function in my classes. Here is my code:

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages
        self.checkedOut = False

    def checked_Out(self):
        print(self.checkedOut)
        return self.checkedOut

    def change_value_of_checkedOut(self):
        if self.checkedOut == False:
            self.checkedOut = True
            print("Switched from False to True.")
        elif self.checkedOut == True:
            self.checkedOut = False
            print("Switched from True to False.")

    def return_pages(self):
        print(self.pages)
        return self.pages

    def return_title(self):
        print(self.title)
        return self.title

    def __str__(self):
        return ("Title: " + self.title + "Author: " + self.author +
                "Pages: " + self.pages + "Checked Out Status: " +
                self.checkedOut)

class Library:
    def __init__(self):
        self.collection = {}

    def addExistingBook(self, book):
        self.collection[book.title] = book.author

    def addNewBook(self, title, author, pages):
        new_book = Book(title, author, pages)
        self.collection[title] = new_book.author

    def change_checked_out_status(self, title):
        if title in self.collection:
            title.change_value_of_checkedOut()
        else:
            print("This book is not in the collection.")

    def __str__(self):
        for myBook in self.collection[myBook]:
            self.collection[myBook]
            self.collection[myBook] = self.author

            # I want to print this return value in my main
        return ("Title: " + self.title + "Author: " + self.author
                + "Pages: " + self.pages + "Checked Out Status: " + self.checkedOut)

def main():
    title = str(input("Enter the title of the book. "))
    author = str(input("Enter the author of the book. "))
    pages = int(input("Enter the number of pages in the book. "))
    myBook = Book(title, author, pages)
    myLib = Library()
    myLib.addExistingBook(myBook)
    myLib2 = Library()
    myLib3 = myLib2.__str__()
    print(myLib3)

main()

It seems like something is wrong with the for loop in my __str__(self) function in the class Library (the idea is that I want the loop to iterate over ever book in the collection) but I'm not sure what the problem is. Here is the error message that I get:

Enter the title of the book. A Tale of Two Cities
Enter the author of the book. Charles Dickens
Enter the number of pages in the book. 434
Traceback (most recent call last):
  File "C:\Python33\Class Programs\lab8.py", line 71, in <module>
    main()
  File "C:\Python33\Class Programs\lab8.py", line 68, in main
    myLib3 = myLib2.__str__()
  File "C:\Python33\Class Programs\lab8.py", line 54, in __str__
    for myBook in self.collection[myBook]:
UnboundLocalError: local variable 'myBook' referenced before assignment

Upvotes: 0

Views: 1000

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1124858

You are looping over the keys of a dictionary, you should not try to pass in a key in the loop statement:

def __str__(self):
    for myBook in self.collection:

It is unclear what you are trying to do with that loop. You are then accessing self.collection[myBook] without doing anything with the return value, then you are replacing the value with self.author (which doesn't exist on self, that is still the library), then you return something completely different as the __str__() result.

I think you want to create a list of your library books here:

def __str__(self):
    return ', '.join('{} - {}'.format(title, author) for title, author in self.collection.items())

Now you return a comma-separated list of all titles and authors in your collection.

There are 3 things going on there:

  • Using a generator expression, we loop over the dictionary .items() method; this generates (key, value) pairs for everything in the dictionary.
  • Each key and value is passed to the str.format() method, using the string as a template to put a - dash between the title and author pairs stored in your self.collection dictionary.
  • The whole loop is passed to the str.join() method; this method takes all the strings from the sequence given to it and concatenates them together with ', ' commas between them.

Next, you are creating an empty library, then print the output of the __str__() method; there is no need to call that explicitly, print() does that for you. Do not create a new library, just print the one you already have:

myLib = Library()
myLib.addExistingBook(myBook)
print(myLib)

Upvotes: 3

dckrooney
dckrooney

Reputation: 3121

I think you want to change

def __str__(self):
        for myBook in self.collection[myBook]:
            self.collection[myBook]
            self.collection[myBook] = self.author

to

def __str__(self):
        for myBook in self.collection.keys():
            self.collection[myBook]
            self.collection[myBook] = self.author

Upvotes: 0

Related Questions