"Object is not subscriptable"

Hi, sorry, noob question. I’m trying to call out and edit products created in my list but keep having the error “‘Product’ object is not subscriptable” when I run below.

The results I want is as per below (index no. + productName):

  1. Orange
  2. Apple
  3. Kiwi
  4. NewProduct Name

Thereafter to select the index no. to edit the product. Can anyone enlighten me how I can call out the productName so that I can edit from there? Many thanks.

class Product:

def __init__(self, name, country, price):

    self.__name = name

    self.__country = country

    self.__price = price

    

def getName(self):

    return self.__name



def setName(self, name):

    self.__name = name

def getCountry(self):

    return self.__country

def setCountry(self, country):

    self.__description = country

def getPrice(self):

    return self.__price

def setPrice(self, price):

    self.__price = price

def __str__(self):

    string = "[" + self.__name + ", "

    string += self.__country + ", "

    string += str(self.__price) + "]" 

    return string

def __repr__(self):

    return f"[{self.__name}, {self.__country}, {self.__price}]"

from Fruits import Product

products =

products.append(Product(“Orange”, “Australia”, 0.8))

products.append(Product(“Apple”, “Japan”, 0.7))

products.append(Product(“Kiwi”, “New Zealand”, 1.1))

def PrintProductDetails(product):

print("Name:", product.getName())

print("Country:", product.getCountry())

print("Price: ${:.2f}".format(product.getPrice()))

productName = input("Name: ")

productCountry = input("Country: ")

productPrice = float(input("Price: "))

NewProduct = Product(productName, productCountry, productPrice)

products.append(NewProduct)

print(products)

#Edit products

print(“Product List”)

for index in range(len(products)):

print(str(index+1) +". ", products[index][0])

editProductIndex = int(input(“Select product to edit\n”))

Thanks.

I’m trying to call out and edit products created in my list but keep
having the error “‘Product’ object is not subscriptable” when I run
below.

It often helpful to also include the full error traceback, because it
often points to the line producting the error. But fortunately it looks
like this is the only place you try to index a Product is here:

for index in range(len(products)):
    print(str(index+1) +". ", products[index][0])

Here, products[index] is one of your Products, and you try to access
element [0] of it. However, a Product is not subscriptable. A list is,
as you’re doing with products[index].

To make a class subscriptable you usually define a getitem method.
When you go:

products[index]

that calls:

products.__getitem__(index)

to fetch that item. In a list (like products) that does the obvious
thing. But you can use it in your own classes, for example maybe to
access a database or extract something from a data structure.

However, it isn’t clear to me why you want to access element [0] from
your Product. What should that mean?

Here’s what you’re after:

The results I want is as per below (index no. + productName):

  1. Orange
  2. Apple
  3. Kiwi
  4. NewProduct Name

Isn’t that the name?

enlighten me how I can call out the productName so that I can edit from
there? Many thanks.

Your class definition says this:

class Product:

def init(self, name, country, price):
self.__name = name
self.__country = country
self.__price = price

def getName(self):
return self.__name
[…]

So Product.getName() returns the name. SO you probably just want to
write your for-loop like this:

for index in range(len(products)):
    print(str(index+1) +". ", products[index].getName())

Does this explain the error, and help you get the product name?

Cheers,
Cameron Simpson cs@cskk.id.au

Hi Irene,

First, a style issue: using two leading underscores is often considered
an advanced technique. You may find it easier as a beginner to just use
single underscores:

self._name = name

or even simple, forget about “data hiding” and just make the attributes
public:

self.name = name

with no need for getters and setters. That’s up to you.

Anyway, that’s not the cause of your problem. Your problem looks like it
is probably this line:

print(str(index+1) +". ", products[index][0])

and specifically the second part:

products[index][0]

products is a list containing Product objects. When you get
products[index] than returns a Product, and then you attempt to do a
subscript item look up inside the product:

product = products[index]
product[0]  # first item of the product object

But that doesn’t work! For it to work you would need to give the Product
class a special __getitem__ method. But that wouldn’t be very helpful,
because a Product is not a list of items.

product[87]  # what would this mean?

Your intention is to grab the name of the product, and for that you
probably need this:

products[index].__name

But that won’t work either! That will lead you straight into the
advanced nature of attributes with leading double underscores.

So here are two strategies, an easy strategy, and a more complicated but
“more correct” strategy. You choose.

Strategy 1: easy.

Remove the double underscores from the instance attributes, making them
fully public:

self.name = name
self.country = country
self.price = price

Then when you want the name of a product, you can just write:

print(product.name)

Strategy 2: more work, but “more correct”.

Leave the double underscores (or change them to singles) as “private”
attributes, but add public iterfaces to retrieve them. In your class,
add properties like this:

@property
def name(self):
    return self.__name

@property
def country(self):
    return self.__country

@property
def price(self):
    return self.__price

That will allow the caller to retrieve the attributes:

print(property.name)

but not modify them:

property.name = 'apple'  # This will fail.

Hope this helps!

Hi, this works. Many thanks for your help.

Many thanks for your advice.