-1

I am attempting to index the book_list object below to be able to access the values of the attributes "title" and "year" in the Books objects (book1 and book2) :

The code:

class Books:
    def __init__(self, title ='', year = 1):
        self.title = title
        self.year = year

    def __getitem__(self):
        return self.title
        return self.year


class BookList(Books):
    def __init__(self):
        self.book_list = []
          
    def store_book(self, book):
        self.book_list.append(book)

    def __getitem__(self):
        return self.book_list[index]

    def showbook(self):
        for book in self.book_list:
            print(book[0], book[1])

book1 = Books('Title 1', 1000)
book2 = Books('Title 2', 1211)
book_list = BookList()
book_list.store_book(book1)
book_list.store_book(book2)
book_list.showbook()

The current output:

TypeError: __getitem__() takes 1 positional argument but 2 were given

The desired output:

Title 1 1000
Title 2 1211
o-90
  • 17,045
  • 10
  • 39
  • 63
  • What is `index` on line 19? – o-90 Aug 27 '22 at 01:39
  • Does this answer your question? [Understanding \_\_getitem\_\_ method](https://stackoverflow.com/questions/43627405/understanding-getitem-method) – sj95126 Aug 27 '22 at 01:47
  • @o-90 book_list contains objects, and the "index" refers to these objects, so object one has an index of 0 .. etc – luca kramp Aug 27 '22 at 02:11
  • @lucakramp I know what index is. My point is that it appears out of nowhere. It is never defined anywhere and is not the argument to any method in your class. – o-90 Aug 27 '22 at 12:42

2 Answers2

0

I tried out your code and made a small tweak. Instead of the following code:

def showbook(self):
    for book in self.book_list:
        print(book[0], book[1])

I believe you just want the following code:

def showbook(self):
    for book in self.book_list:
        print(book.title, book.year)

When I tested the program with that tweak, the following was the output on my terminal.

@Una:~/Python_Programs/Books$ python3 Books.py 
Title 1 1000
Title 2 1211

Test that out and see if it resolves your issue.

Additional notes to respond to your comment.

It appears that when attributes in the initialization function are defined as you have them, they are just that, individual attributes and are not treated like a list that can be indexed. Expanding upon that, I did redo the initialization function as follows:

class Books:
    def __init__(self, title ='', year = 1):
        self.book = []
        self.book.append(title)
        self.book.append(year)

Then, these attributes were a part of a list, and your original block of code worked.

    def showbook(self):
        for book in self.book_list:
            print(book[0], book[1])

The bottom line is that Python appears to be fussy in how attributes are defined within the class.

NoDakker
  • 3,390
  • 1
  • 10
  • 11
  • it seems to work, but why i couldnt use the indexes, why not book[0] instead of book.title ? – luca kramp Aug 27 '22 at 02:16
  • I doubled back to the code and did a different tweak. See the revised answer above. It boils down to how you want to set up you classes attributes. – NoDakker Aug 27 '22 at 02:54
0

You need to provide an index to __getitem__ if you want to use it as book[0]

In [1]: class Books:
   ...:     def __init__(self, title ='', year = 1):
   ...:         self.data = (title, year)
   ...: 
   ...:     def __getitem__(self, idx):
   ...:         if idx < 2:
   ...:             return self.data[idx]
   ...:         else:
   ...:             raise IndexError
   ...: 
   ...: 
   ...: class BookList(Books):
   ...:     def __init__(self):
   ...:         self.book_list = []
   ...: 
   ...:     def store_book(self, book):
   ...:         self.book_list.append(book)
   ...: 
   ...:     def __getitem__(self, index):
   ...:         return self.book_list[index]
   ...: 
   ...:     def showbook(self):
   ...:         for book in self.book_list:
   ...:             print(book[0], book[1])
   ...: 
   ...: book1 = Books('Title 1', 1000)
   ...: book2 = Books('Title 2', 1211)
   ...: book_list = BookList()
   ...: book_list.store_book(book1)
   ...: book_list.store_book(book2)
   ...: book_list.showbook()
Title 1 1000
Title 2 1211

If you want to use book['title'] then modify few lines:

In [2]: class Books:
   ...:     def __init__(self, title ='', year = 1):
   ...:         self.data = {'title': title, 'year': year}
   ...: 
   ...:     def __getitem__(self, idx):
   ...:         return self.data[idx]

And then modify the showbook as:

   ...:     def showbook(self):
   ...:         for book in self.book_list:
   ...:             print(book['title'], book['year'])
Osman Mamun
  • 2,864
  • 1
  • 16
  • 22