Reputation: 48
I am trying to make a minecraft resource calculator in Python, but as it will have a decent number of items I feel like using a bunch of if statements to determine user input isn't the best way I could do it.
def hoppercalc():
print(noofitems * 5, "iron")
def pistoncalc():
print(noofitems * 3, "planks,",
noofitems * 4, "cobblestone,",
noofitems, "redstone and iron")
noofitems = int(input("How many items do you want to make? "))
itemname = input("What item do you want to make? ")
if itemname == "hopper":
hoppercalc()
if itemname == "piston":
pistoncalc()
Upvotes: 1
Views: 393
Reputation: 1825
I suggest below methods, where you don't have to make your own dictionary or list, and use your programs scope to get all things you defined
You can look into sequence of elements from locals and get itemname, if it exists then it will execute
locals().get(itemname + 'calc') and locals().get(itemname + 'calc')()
In this case outermost main function, so you can also use globals
globals().get(itemname + 'calc') and globals().get(itemname + 'calc')()
I use .get
on dictionary because if function does not exist it will return None
. None
evaluates to False
so it will not execute next boolean statement
locals will get all instances existing in the present scope, while global gets all globals. Other than these you also have
You can evaluate expression if you trust the input. Eval comes with its own draw back and if user is not trusted it can even delete files for example
eval(itemname + 'calc()')
Upvotes: 0
Reputation: 66
This will help. but this is not the best way to do. you should use dictionary datatype.
def f1():
print("func one")
def f2():
print("func two")
def f3():
print("func three")
def f4():
print("func four")
func_list = [f1, f2, f3, f4]
word_list = ["one", "two", "three", "four"]
val = input("Enter :")
for x in range(len(word_list)):
if word_list[x] == val:
func_list[x]()# call the function in list corresponds to list
else:
print("wrong entry")
Upvotes: 0
Reputation: 47860
I'd think about this a little differently. Instead of making a function for each item recipe, just make a table that represents the ingredient quantities, then you can do lookups in it with a single calculation function:
recipes = {
"hopper": {"iron": 5},
"piston": {"planks": 3, "cobblestone": 4, "redstone": 1, "iron": 1},
}
def show_recipe(item, quantity=1):
ingredients = recipes[item]
for name, amount in ingredients.items():
print(amount * quantity, name)
show_recipe("piston", 2)
This prints:
6 planks
8 cobblestone
2 redstone
2 iron
Now adding a new recipe just involves adding a line in the table, instead of writing a whole new function. If you want to get more sophisticated you can move to having Enum
classes to represent your items and ingredients, and then put the recipe method on the item class, and so on.
Also note that I made the item quantity a parameter to the function; this is in general a good idea instead of using a global.
Upvotes: 2
Reputation: 33
A dirty but quick fix is to take one function calc that gets an attribute itemname. Inside that function, if itemname is hopper, do thee code of hoppercalc, else do the code of pistoncalc.
I'd still recommend a dictionary though. https://docs.python.org/3/tutorial/datastructures.html#dictionaries
Some examples here: https://www.programiz.com/python-programming/dictionary
Upvotes: 0
Reputation: 29
How about getting rid of two functions and using one?
def calc():
if itemname == "hopper":
print(noofitems * 5, "iron")
elif itemname == "piston":
print(noofitems * 3, "planks,", noofitems * 4, "cobblestone,",
noofitems, "redstone and iron")
return
Upvotes: 0
Reputation: 24164
You could map the item name to the calculation function:
calculations = {'hopper': hoppercalc,
'piston': pistoncalc}
calculations[itemname]()
Upvotes: 0