I'm really new to Python (like only a month of study) and I was testing out dictionaries, so I tried to make an 'inventory' where you can pick an item from your inventory and examine it. But I can tell that I'm not doing this in the most efficient or elegant way.
Originally I thought I could make each item its separate dictionary, kind of like this:
#define what's in your inventory using a list
inventory = ["apple", "tire"]
#create a list of items with attributes using dictionaries
apple = {
"name":"apple",
"type":"fruit",
"edible":"edible",
"color":"red",
}
tire = {
"name":"tire",
"type":"object",
"edible":"not edible",
"color":"grey"
}
#explain the program to the user
print("Choose an item to examine. Items in your inventory are:")
print(*inventory, sep = ", ")
#set the loop to true
itemsloop = True
#begin the loop
while itemsloop == True:
#ask for user input
x = input()
But then I got stuck at the part where it's time to take the input and match it to the name of a dictionary, because one is a string and one isn't. The following code is working, but feels... inelegant and unnecessary to type out (prefix)-name, (prefix)-type, (prefix)-edible for every entry. I feel like there must be a simpler way to accomplish this that I'm just not seeing because I don't think like a programmer yet. I don't know.
If you can explain any more efficient methods with simple terminology (again, huge newbie not just to Python but programming in general), I'd really appreciate it!
#define what's in your inventory using a list
inventory = ["apple", "tire"]
#create a list of items with attributes using a dictionary
items = {
"apple-name":"apple",
"apple-type":"fruit",
"apple-edible":"edible",
"apple-color":"red",
"tire-name":"tire",
"tire-type":"object",
"tire-edible":"not edible",
"tire-color":"grey"
}
#explain the program to the user
print("Choose an item to examine. Items in your inventory are:")
print(*inventory, sep = ", ")
#set the loop to true
itemsloop = True
#begin the loop
while itemsloop == True:
#ask for user input
x = input()
if x in inventory:
#if the input matches something you have, find the attributes of
#the item in the inventory and print them.
print("This is a " + items[x + "-color"] + " " +
items[x + "-name"] + ", a type of " + items[x + "-type"]
+ ". It is " + items[x + "-edible"] + ".")
elif x == "quit":
#if the player wishes to quit, end the program.
itemsloop == False
break
else:
#if the item is not recognized, let the player know.
print("You don't have that in your inventory.")
(The sample output would be something like, "This is a red apple, a type of fruit. It is edible.")
2 Answers 2
To expand on the answer given by @Aries_is_there in, you should indeed make your dictionary a nested dictionary with the item names as first keys and the item properties as keys of the sub dictionaries.
You should also be aware that x in inventory
is \$\mathcal{O}(n)\$ if inventory
is a list, but this is mitigated when making it a dictionary, because x in items
is \$\mathcal{O}(1)\$ for dictionaries.
Your printing can also be simplified by using an f-string
.
I would also add a if __name__ == "__main__"
guard to allow importing functions form this script from another script.
And finally, Python has an official style-guide, PEP8, which is well worth a read. You are already mostly following it, except for the missing spaces after the :
in your dictionaries.
items = {"apple": {"name": "apple",
"type": "fruit",
"edible": "edible",
"color": "red"},
"tire": {"name":"tire",
"type":"object",
"edible":"not edible",
"color":"grey"}}
if __name__ == "__main__":
print("Choose an item to examine. Items in your inventory are:")
print(*items.keys(), sep = ", ")
while True:
x = input()
if x in inventory:
#if the input matches something you have, find the attributes of
#the item in the inventory and print them.
item = items[x]
print(f"This is a {item['color']} {item['name']}, a type of {item['type']}. It is {item['edible']}.")
elif x == "quit":
#if the player wishes to quit, end the program.
break
else:
#if the item is not recognized, let the player know.
print("You don't have that in your inventory.")
You could take it one level further by making it object-oriented. In this case you would probably want an Object
class for which you define the magic __str__
method, which controls what happens if you do print(x)
.
class Object:
def __init__(self, name, type="object", edible=False, color=None):
self.name = name
self.type = type
self.edible = edible
self.color = color
def __str__(self):
s = ["This is a "]
if self.color is not None:
s.append(self.color + " ")
s.extend([self.name, f", a type of {self.type}."]
s.append(f"It is {'not ' if not self.edible else ''}edible.")
return "".join(s)
items = {"apple": Object("apple", "fruit", edible=True, color="red"),
"tire": Object("tire", color="grey")}
if __name__ == "__main__":
print("Choose an item to examine. Items in your inventory are:")
print(*items.keys(), sep = ", ")
while True:
x = input()
if x in items:
#if the input matches something you have, find the attributes of
#the item in the inventory and print them.
item =
print(items[x])
elif x == "quit":
#if the player wishes to quit, end the program.
break
else:
#if the item is not recognized, let the player know.
print("You don't have that in your inventory.")
-
\$\begingroup\$ Thank you very much for the thorough explanation. I didn't know you could nest dictionaries! I'm still new to a lot of the things included in your post, so i will be doing googling for a while, haha. Do you have any recommendations on a good newbie explanation for magic methods? I had never heard of those. \$\endgroup\$Red– Red2018年11月14日 18:09:54 +00:00Commented Nov 14, 2018 at 18:09
As you use item's name
to search the item information
, so you can design the name
as the key of items
hash table.
items = {
"apple":
{
#type, edible,color information
},
...
}
-
\$\begingroup\$ I didn't understand that you could use dictionaries as dictionary keys. Thank you. \$\endgroup\$Red– Red2018年11月14日 17:57:37 +00:00Commented Nov 14, 2018 at 17:57
-
\$\begingroup\$ haha as long as you get @Graipher answer, he did a good explain \$\endgroup\$Aries_is_there– Aries_is_there2018年11月14日 18:22:36 +00:00Commented Nov 14, 2018 at 18:22
-
1\$\begingroup\$ @Red You actually can't. But you can use them as dictionary values. If you want to use them as keys you would have to convert the dictionary into a tuple of
key, value
tuples first, so it is hashable. This would be sensitive to the order then, though. \$\endgroup\$Graipher– Graipher2018年11月14日 19:17:40 +00:00Commented Nov 14, 2018 at 19:17