I need to find the discount of an order I used the following code to make the string input of order numbers to a dictionary and thenused sum() to find the total of the order However I wish to have an offer discount if there is one-1 and one-3 and (one-4 or one-5 or one-6) But then after the conditional block when I want to multiply it I receive an Unbound Error
def compute_cost(order):
"""
Function 2: compute_cost(order)
Parameters: order (String)
Return: Final cost of order
"""
numcount = {}
orderlist = map(int, order)
for i in orderlist:
if numcount.get(i):
numcount[i] += 1
else:
numcount[i] = 1
for i in numcount:
if i == 1:
numcount[i] = numcount[i]*4.25
elif i == 2:
numcount[i] = numcount[i]*2.50
elif i == 3:
numcount[i] = numcount[i]*2.00
elif i == 4:
numcount[i] = numcount[i]*1.25
elif i == 5:
numcount[i] = numcount[i]*1.50
elif i == 6:
numcount[i] = numcount[i]*1.75
elif i == 7:
numcount[i] = numcount[i]*3.75
else:
return print("Your order has a number outside of the range (1:7)")
order_total = sum(numcount.values())
if(numcount[1] == 1 and
numcount[3] == 1 and
(numcount[4] == 1 or
numcount[5] == 1 or
numcount[6] == 1)):
discount1 = 0.20
order_total1 = order_total*discount1
return order_total1
Please help me Thank you for your time and effort
EDIT If you have a better way for me to find the values and save them in a dictionary I am open to constructive criticism too
Depending on the input, the numcount-dict may or may not have all the keys.
Case 1: UnboundLocalError
When calling the function with compute_cost('12323123')
, the numcount
-dict becomes:
{1: 2, 2: 3, 3: 3}
The if-statement first checks if numcount[1] == 1
, which evaluates to False. Therefore the whole expression is False and Python doesn't even (need to) check the rest. (This is called short-circuit evaluation.)
Because the if-statement evaluates to False, discount1
is not set at all, so you get UnboundLocalError: local variable 'discount1' referenced before assignment
.
Solution:
Add an else-clause that sets discount1
to 1 (= no discount) when the condition is False:
if (numcount[1] == 1 and numcount[3] == 1 and (numcount[4] == 1 or
numcount[5] == 1 or numcount[6] == 1)):
discount1 = 0.20
else:
discount1 = 1
Case 2: KeyError
Now, when calling the function with compute_cost('32235664')
, the numcount
-dict becomes:
{3: 2, 2: 2, 5: 1, 6: 2, 4: 1}
The if-statement first checks if numcount[1] == 1
, but that key does not exist so Python raises a KeyError
. Depending on your input and how far Python needs to evaluate the if
-statement, you may get that KeyError
or not.
Solution:
Make sure that the numcount
-dict contains all keys from the beginning. You already know how many items the dict must have because you limit your input to the range (1:7). Therefore you can initalize the dict as:
numcount = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0}
EDIT: is there a better way?
Sure there is, there almost always is a better way:
prices = {'1':4.25, '2':2.50, '3':2.00, '4':1.25, '5':1.50, '6':1.75, '7':3.75}
orders = '12323456'
total = sum(prices[order] for order in orders)
if (all(orders.count(type) >= 1 for type in '13') and # multiple ANDs with 'all'
any(True for type in '456' if orders.count(type) >=1)): # multiple ORs with 'any'
discount = 0.2
else:
discount = 1
print('Order value: {}\nDiscount: {}\nOffer: {:.2f}'.format(total, discount, discount * total))
You now can easily extend your prices dictionary or the conditions for a discount. I assumed that the condition for a discount is that at least one item was ordered, not exactly one. Therefore I used >=1
which you can change into ==1
if it needs to be exactly one.