Python Forum
Calling an class attribute via a separate attribute in input - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Homework (https://python-forum.io/forum-9.html)
+--- Thread: Calling an class attribute via a separate attribute in input (/thread-25585.html)



Calling an class attribute via a separate attribute in input - wiggles - Apr-04-2020

Hi, am trying to call a class attribute but am unable to get it to work. When the user inputs the Item.code into a float input, I want to display

"You have selected (Item.name) which is (Item.price). Currently (Item.amount) in stock."

I have read through the basics of Classes on the website, and Inheritance and Overloading. But I can't work out how to refer to the other Item attributes. I can always revert back to just lists, but I know that isn't good code.

Any help would be appreciated.

Code below

class Item:
    def __init__(self, code, name, price, amount):
        self.code = code
        self.name = name
        self.price = price
        self.amount = amount


class VendingMachine:

    def __init__(self):

        self.items = [
            Item(1, "Tea", 0.50, 10),
            Item(2, "Coffee", 1.00, 10),
            Item(3, "Coke", 1.50, 6),
            Item(4, "Orange Juice", 1.00, 5)
        ]



RE: Calling an class attribute via a separate attribute in input - ndc85430 - Apr-04-2020

I don't understand the problem. To access an attribute, you just use a dot on your instance, e.g.

>>> class Item:
...     def __init__(self, code, name, price, amount):
...         self.code = code
...         self.name = name
...         self.price = price
...         self.amount = amount
...  
... 
>>> my_item = Item(1, "Tea", 0.50, 10)
>>> my_item.price
0.5



RE: Calling an class attribute via a separate attribute in input - buran - Apr-04-2020

I would advise that you use dict, instead of list, e.g.

class Item:
    def __init__(self, code, name, price, amount):
        self.code = code
        self.name = name
        self.price = price
        self.amount = amount

class VendingMachine:
  
    def __init__(self):
  
        self.items = {'1':Item(1, "Tea", 0.50, 10),
                      '2':Item(2, "Coffee", 1.00, 10),
                      '3':Item(3, "Coke", 1.50, 6),
                      '4':Item(4, "Orange Juice", 1.00, 5)}

vending = VendingMachine()
user_choice = input('Item code (1-4):')
item = vending.items[user_choice]
print(f"You have selected {item.name} which is {item.price}. Currently {item.amount} in stock.")
Output:
Item code (1-4):3 You have selected Coke which is 1.5. Currently 6 in stock.



RE: Calling an class attribute via a separate attribute in input - deanhystad - Apr-04-2020

In the example you provide there is no relationship between the key and value other than order. Why do you think a dictionary better than a list in this case? Since the item code will be an integer, or at least easily converted to an integer, vending_items[choice] == vending_items[choice]. Are you suggesting the dictionary to remove converting user input from a string to an int or is there something more subtle?


RE: Calling an class attribute via a separate attribute in input - buran - Apr-04-2020

(Apr-04-2020, 10:42 AM)deanhystad Wrote: In the example you provide there is no relationship between the key and value other than order.

That's not true, the key is the code of the item (but str, not int). As per OP explanation, user will be required to provide item code. I.e. if the code was something different - e.g. alphanumeric code, it will be used as key. Nothing t do with order.

(Apr-04-2020, 10:42 AM)deanhystad Wrote: Why do you think a dictionary better than a list in this case?

Because that is the easiest way to access specific item from collection. if you use list instead you will need to iterate over list of items in order to find the item with code provided by user. There are different collections and you should choose the best for the task at hand.

(Apr-04-2020, 10:42 AM)deanhystad Wrote: Are you suggesting the dictionary to remove converting user input from a string to an int or is there something more subtle?

You are close... As I said keys are str, not int like the item code so that we don't convert user input to int.

Note that this is just an example. You can make it more dynamic, validate user input and so on...


RE: Calling an class attribute via a separate attribute in input - wiggles - Apr-04-2020

Hi - thanks guys. Unfortunately if change the list to a dict as Buran suggests, that it impacts me down the line when I try to use enumerate on the items to outline the list - see below

class Item:
    def __init__(self, code, name, price, amount):
        self.code = code
        self.name = name
        self.price = price
        self.amount = amount


class VendingMachine:

    def __init__(self):

        self.items = [
            Item(1, "Tea", 0.50, 10),
            Item(2, "Coffee", 1.00, 10),
            Item(3, "Coke", 1.50, 6),
            Item(4, "Orange Juice", 1.00, 5)
        ]
    def display_items(self):
        for code, item in enumerate(self.items, start=1):
            print(f"[{code}] - {item.name} - (${item.price:.2f})")
Any chance I could the key that has been outlined above in the method display_items? Or is that something different?

Wiggles


RE: Calling an class attribute via a separate attribute in input - deanhystad - Apr-04-2020

I have a vending machine at work with number and letter keys. Number keys are for columns and letters for rows. I punch a number and a letter and it gives a position in a grid. For example, pressing M5 selects a Coke and pressing C6 a strawberry flavored water. Using a list it would take a little more work to convert button presses into a selection because I would have to search through al the possible selections and compare the selection to a selection ID for the item. Using a dictionary as buran suggests it is simple because the button combination is a key in the dictionary.

For your example where you have items 1, 2, 3... you can use a list or a dictionary. The number would be the position of the item in a list or the key for a dictionary. Essentially a list is a restricted dictionary where a numerical index is the key used to access the value. The nice thing about the dictionary is the key no longer has to be numeric and you can make a vending machine program that works like my soda vending machine.


RE: Calling an class attribute via a separate attribute in input - wiggles - Apr-04-2020

Thanks guys. I have solved it using the dict method.

Appreciate the time you guys took to look over it for me