Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object has no attribute '__getitem__' (class instance?)

Tags:

python

class

It might be a very simple question but I am very confused with where I am going right now. Here is a very basic class:

class Book(object):
    def __init__(self, title, price):
        self.book = {'title':title, 'price':price}

And when I run this:

book = Book('foo', 300)
book['price']

It spits out:

TypeError: 'Book' object has no attribute '__getitem__'

I know that it's not the conventional way of initializing an instance since I am using a dictionary. But I wonder why that code is spitting out a TypeError. How do I go about solving this issue? Thank you in advance.

ps. The book instance's type is class?

like image 685
Joseph Seung Jae Dollar Avatar asked Jun 11 '15 07:06

Joseph Seung Jae Dollar


3 Answers

It's because a class is not a dict object. Accessing properties on a instance of a class is done via the dot operator.

book.book['price'] 
>> 300

If you want to access keys within your dict directly on your class instance you would have to implement the __getitem__ method on your class.

def __getitem__(self, key):
    return self.book[key]

book['price']
>> 300
like image 82
Henrik Andersson Avatar answered Nov 16 '22 07:11

Henrik Andersson


Yes. book is an object of class Book because you initialized it that way.

book = Book('foo', 300)
book['price']

Try

print book.book['price']

So you want to access a dictionary called book of an object referenced as book and you want to extract the value of price from the dictionary.

Usually [] operator looks for __getitem__() method and passes the requested key as an argument. Łukasz R. has shown how to do that. Dictionaries perform a key lookup while arrays find the slice or index.

It is explained in details here : https://docs.python.org/2/reference/datamodel.html

Now because you're creating a class here, why do you want to create a separate dictionary for native must-have attributes of the class. Create attributes like the following example:

class Book(object):
    def __init__(self, title, price):
        self.title = 'foo'
        self.price = 300

book = Book('foo', 300)
print book.title
like image 7
Aditya Avatar answered Nov 16 '22 07:11

Aditya


book.book['price'] would work. For accessing proxy member you'll have to implement __getitem__ magic method.

class Book(object):
    def __init__(self, title, price):
        self.book = {'title':title, 'price':price}
    def __getitem__(self, item):
        return self.book[item]
like image 3
Łukasz Rogalski Avatar answered Nov 16 '22 09:11

Łukasz Rogalski