How do I search for a class element in a list?

I’m trying to search for an item, but no matter what I input, even when I search for something that is in the list, it returns the else statement.
[python]
def itemSearch(listItems):
userSearch = str(input("Enter the name of the item to find. "))
if userSearch in listItems:
print(“You have”, listItems[i].getQuantity(), listItems[i].getName(), “at a price of $”, listItems[i].getPrice(), “each”)
else:
print(“That item is not in the list.”)
[/codebyte]
I’m not super experienced in Python, or coding in general, but I can’t seem to figure out what’s going wrong.

Functions should take inputs via the parameters. Best practice would suggest getting user input before calling the function.

def itemSearch(items, item):
    pass

itemSearch(input('Enter the item to find: '))

Likewise, print at the caller, not inside the function. Have it return a value, instead.

def itemSearch(items, item):
    if item in items:
        return f"... {___} {___} at a price of ${___}"
    else:
        return "..."

print (itemSearch(input('Enter the item to find: ')))

This will make your functions more compact and easier to read and debug, as well as make them single purpose.

Next we should examine the data structure and the user input. Are there dict objects stored in a list? What will the input be, the name of the item?

It would appear your class has getters for each attribute. How will that effect the search?

Please post your entire class code so we can see how it is constructed.

Thanks for your response! Here is the class code in its entirety.

class item: def __init__(self, name, quantity, price): self.myName = name self.myQuantity = quantity self.myPrice = price def __str__(self): """Returns the string representation of an item""" result = "Name: " + str(self.myName) + "\n" result += "Quantity: " + self.myQuantity + "\n" result += "Price: " + self.myPrice + "\n" return result #getters for the instance variables def getName(self): """Returns the Name of the item""" return self.myName def getQuantity(self): """Returns the Quantity of the item""" return self.myQuantity def getPrice(self): """Returns the Price of the item""" return self.myPrice #setters for the instance variables def setName(self): """Set the Name of the item""" self.myName = name def setQuantity(self): """Set the Quantity of the item""" self.myQuantity = Quantity def setPrice(self): """Set the Price of the item""" self.myPrice = Price

It’s really not necessary to create unique names. One is an attribute, the other a parameter.

self.name = name
self.quantity = quantity
self.price = price

As for your __str__() method, using the f-string syntax we can directly interpolate the variables without casting or concatenation.

return f"Name: {self.name}\nQuantity: {self.quantity}\nPrice: {self.price}"

As for the getters and setters, they are kind of redundant since they don’t do anything special. Not sure camelCase names are common to Python where we are more likely to find snake_case names.

get_name
get_quantity
get_price

One could give the attributes some pseudo-privacy…

self._name = name

def get_name(self):
    return self._name

def set_name(self, value):
    self._name = value    # could be validated here

Now we’re assuming you are appending a list with new instances…

stock = []
stock.append(Item('trainers', 20, 149.99))
stock.append(Item('jerseys', 20, 89.99))
stock.append(Item('shorts', 20, 59.99))

So now how do we search for ‘trainers’ in that list?

Would ‘trainers’ be added to the list as a string, therefore requiring the user input to be a string?

User input will be a string since that is what input() returns. In the instance creation because of its position in the argument list it will be assigned to self.name through the name parameter. Dynamically it will not lose its type.

If we write the instance call, as we’ve done above, the quotes are a must else they are treated as identifiers.

The number values if taken from user input will need casting. It’s not likely we would be entering data through this program but rather getting it in the form a spreadsheet data such as, CSV. Each row in the sheet would be added by a program that would instance it and append to the stock list. In the case of search, we’re not looking for numbers, but items by name.

So that becomes a constraint of our search parameters… Item name. Since inputs are strings, even numbers can be passed in as part numbers, ids, even hashes.

In ‘stock’ can we find the index of the dict containing that name?

Didn’t find the index but found the item…

>>> stock
[<__main__.Item object at 0x0000015618597FA0>, <__main__.Item object at 0x00000156185B56D0>, <__main__.Item object at 0x00000156185B55B0>]
>>> stock[0].get_name()
'trainers'
>>> trainers = [*filter(lambda x: x.get_name() == 'trainers', stock)]
>>> trainers[0].get_name()
'trainers'
>>> 

Very important to keep in mind that we are not using any Python power, only the .get_name() method of that object. Were it not an Item instance, it would not have that method.


Now bend you head around this one…

>>> trainers = filter(lambda x: x.get_name() == 'trainers', stock)
>>> next(trainers).get_name()
'trainers'
>>> 

A filter object is an iterator, which means it has a __next__ attribute. If we repeat that line we will get a StopIteration exception since the iterator is consumed.

This may be fringe worthy at present, expect it to come up a lot in your travels.