Getting UnboundLocalError while executing the program - python

I am writing a code for an application in Python. So far I have written this. I am getting an error at line 68 i.e. shopping_list = shopping_list.append(temp_df, ignore_index=True). The error message is given right after the code. I need to make a list where I am appending all the items added to the cart.
import sys
class Shopping:
def add_item(self):
items = int(input('Enter the number of items you want to send'))
for i in range(0, items):
print('Enter the details for the item')
type_pack = input('Enter the type(letter or parcel):')
weight = input('Enter the weight of the product: ')
destination = input('Enter the destination of the product: ')
zone = countries_zones.loc[countries_zones['Destination'] == destination.capitalize(), 'Zones'].iloc[0]
zone1 = int(zone[-1])
cost = 0
if type_pack.lower() == 'parcel':
if float(weight) < 3:
cost = parcel_by_sea_dataset[zone][parcel_by_sea_dataset.Weight == 'Over 2.5 kg up to 3kg'].iloc[0]
if cost == '-':
print("Sorry, no parcel services available for ", destination)
print('The cost of your stamp is', cost)
elif 3 <= float(weight) < 5:
cost = parcel_by_sea_dataset[zone][parcel_by_sea_dataset.Weight == 'Up to 5kg'].iloc[0]
if cost == '-':
print("Sorry, no parcel services available for ", destination)
print('The cost of your stamp is', cost)
elif 5 <= float(weight) < 10:
cost = parcel_by_sea_dataset[zone][parcel_by_sea_dataset.Weight == 'Up to 10kg'].iloc[0]
if cost == '-':
print("Sorry, no parcel services available for ", destination)
print('The cost of your stamp is', cost)
elif 10 <= float(weight) < 15:
cost = parcel_by_sea_dataset[zone][parcel_by_sea_dataset.Weight == 'Up to 15kg'].iloc[0]
if cost == '-':
print("Sorry, no parcel services available for ", destination)
print('The cost of your stamp is', cost)
elif 15 <= float(weight) < 20:
cost = parcel_by_sea_dataset[zone][parcel_by_sea_dataset.Weight == 'Up to 20kg'].iloc[0]
if cost == '-':
print("Sorry, no parcel services available for ", destination)
print('The cost of your stamp is', cost)
else:
print("please enter a number between 0-20")
print('Please chose the option below')
print('1. Add to cart')
print('2. Go back')
selection = input('Enter your choice: ')
if selection == '1':
temp_df = pd.DataFrame({'Item Type': [type_pack],
'Weight': [weight],
'Destination': [destination],
'Cost': [cost]})
shopping_list = shopping_list.append(temp_df, ignore_index=True)
print(shopping_list)
def delete_item(self):
pass
def amend_item(self):
pass
def print_list(self):
pass
def print_receipt(self):
pass
Traceback (most recent call last):
File "C:/Divyam Projects/oops1/stamp.py", line 114, in <module>
mainMenu()
File "C:/Divyam Projects/oops1/stamp.py", line 99, in mainMenu
shopping.add_item()
File "C:/Divyam Projects/oops1/stamp.py", line 68, in add_item
shopping_list = shopping_list.append(temp_df, ignore_index=True)
UnboundLocalError: local variable 'shopping_list' referenced before assignment
Thank you for your help in advance. :)

You are trying to use the shopping list and append something to it, but it was never created.
try this:
shopping_list = []
shopping_list.append(something,ignore_index=true)
you can declare the shopping_list above your class

The error states:
UnboundLocalError: local variable 'shopping_list' referenced before assignment
This means you are attempting to do something with a variable that doesn't exist yet. The solution is to declare it before you try to use it, probably directly below the line where you declare items in this function.
Another problem will arise: .append() has no return value, so shopping_list will become None if you assign the return value of .append() to it. In fact, .append() modifies the list in-place; there is no need to assign anything when appending.
Clarification:
# Incorrect
foo = []
foo.append('bar')
# foo is now None
# Correct
foo = []
foo.append('bar')
# foo is now ['bar']

Related

Budget tracker program not working in Linux

I am trying to improve this program. I am working with Linux. I want to add a menu function where the user can pick an option and based on the option call the respective function, but the program is not working, when I run it in the Terminal it doesn't do anything and doesn't show any errors. Please, I need help to solve the problem and make the program works. Thanks!
Here's what I have so far, still there are some functions that need to develop:
#! /usr/bin/python3
import sys
def menu(self):
print ("""
1. Add an Expense
2. Remove an Expense
3. Add revenue
4. Remove Revenue
5. Exit
""")
option = input ("What would you like to do [Number Only]?")
if option == "1":
self.add_expense()
elif option == "2":
self.remove_expense()
elif option == "3":
self.add_revenue()
elif option == "4":
self.remove_revenue()
else:
self.reset_program()
self.close_program()
return option
def add_expense(self):
def __init__(self):
self.month_balance = 0
self.expenses = 0
self.expense_list = []
self.expense_name = []
self.month_balance_name = []
self.month_balance_list = []
self.prompt_income()
def month_balance_ask(self):
add_month_balance = input('Add monthly balance? [y/n]: ')
return add_month_balance
def month_balance_sum(self):
self.month_balance = sum(self.month_balance_list)
def expense_ask(self):
add_expense = input('Add expense? [y/n]: ')
return add_expense
def expense_sum(self):
self.expenses = sum(self.expense_list)
def month_balance_check(self):
if not self.month_balance_list:
print('Please enter at least one monthly balance. ')
self.prompt_month_balance()
def expense_check(self):
if not self.expense_list:
print('Please enter at least one expense. ')
self.prompt_expense()
def prompt_month_balance(self):
x = False
while not x:
result = self.month_balance_ask()
if result == 'y':
month_balance_input = int(input('Enter monthly balance. [Numbers Only]: '))
self.month_balance_list.append(month_balance_input)
month_balance_name = input('Enter monthly balance name. [Name Only]: ')
self.month_balance_name.append(month_balance_name)
else:
self.month_balance_check()
x = True
self.month_balance_sum()
name = [name for name in self.month_balance_name]
month_balance = [month_balance for month_balance in self.month_balance_list]
month_balancedict = dict(zip(name, month_balance))
for k in incomedict:
print(k + ': ', '$' + str(month_balancedict[k]))
print('Total user monthly balance: ', '$' + str(self.month_balance))
self.prompt_expense()
def prompt_expense(self):
x = False
while not x:
result = self.expense_ask()
if result == 'y':
expense_input = int(input('Enter expense amount. [Numbers Only]: '))
self.expense_list.append(expense_input)
expense_name = input('Enter expense name. [Name Only]: ')
self.expense_name.append(expense_name)
else:
self.expense_check()
x = True
self.expense_sum()
name = [name for name in self.expense_name]
expense = [income for income in self.expense_list]
expensedict = dict(zip(name, expense))
for k in expensedict:
print(k + ': ', '$' + str(expensedict[k]))
print('Total user expenses: ', '$' + str(self.expenses))
self.added_expense()
def added_expense(self):
expenseadded = self.month_balance - self.expenses
if expenseadded < 0:
print('You are in the negative, you have a deficit of ' + '$' + str(expenseadded))
if expenseadded == 0:
print('You have broken even, you are spending exactly as much as you make.')
if expenseadded > 0:
print('You are in the positive, you have a surplus of ' + '$' + str(expenseadded))
another = input('Would you like to run another analysis? [y/n]: ')
if another == 'y':
self.menu()
else:
self.reset_program()
self.close_program()
def remove_expense(self):
print("code goes here")
def add_revenue(self):
print("code goes here")
def remove_revenue(self):
print("code goes here")
def reset_program(self):
self.month_balance = 0
self.expenses = 0
del self.expense_list[0:]
del self.expense_name[0:]
del self.month_balance_name[0:]
del self.month_balance_list[0:]
self.prompt_month_balance()
def close_program(self):
print('Exiting Program.')
sys.exit(0)

Python elif statements are changing type from float to list

First time posting so apologizes if formatting is incorrect. My program has 2 lists for now. I I will be adding 4 more after solving this initial issue. One for and item the user selects, and a second with prices for the each item. I have written a code for user selection which runs.
My issue comes with the code for the program associating the item selected with the price list. My first if statement registers item_price as a float, which I gives me what I need. Item_price in the following elif statements are being seen as a list. How can I change them to a float so that the price prints instead of the list?
food=["burger", "pizza", "hotdogs", "tacos"]
food_price=[8.99, 22.50, 3.50, 6.00]
def get_menu_item(item,item_list,):
phrase = "Would you like" + item + "? [y/n] "
response = input(phrase)
if response == "y":
print("Here are your menu options:", item_list)
idx = input("please enter the item you would like from our menu[1,2,3,4]: ")
idx = int(idx) -1
return item_list[idx]
#if user selects [n]
else:
return (None)
#item price function
def get_item_price(item_price,item,item_list):
if item == item_list[0]:
item_price = item_price[0]
elif item == item_list[1]:
item_price == item_price[1]
elif item == item_list[2]:
item_price == item_price[2]
elif item == item_list[3]:
item_price == item_price[3]
return item_price
entree_choice = get_menu_item(" dinner",food)
print('You have selected: ' + entree_choice + ".")
entree_price = get_item_price(food_price,entree_choice,food)
print(entree_price)
I answered this for myself shortly after. I was using == instead of = for all of my elif statements. I feel dumb but writing this out helped me solve it.
You could simplify things further by using a dictionary to store your data :
food_price = {"burger":8.99, "pizza":22.50, "hotdogs":3.50, "tacos":6.00}
def get_menu_item(item,item_list,):
phrase = "Would you like" + item + "? [y/n] "
response = input(phrase)
if response == "y":
print("Here are your menu options:", item_list)
idx = input("please enter the item you would like from our menu[1,2,3,4]: ")
idx = int(idx) -1
return item_list[idx]
else:
return (None)
entree_choice = get_menu_item(" dinner",food)
print('You have selected: ' + entree_choice + ".")
# if entree_choice is not found in the food_price dictionary, the output becomes the string "Entree choice not available."
entree_price = food_price.get(entree_choice, "Entree choice not available.")
print(entree_price)

Parsed value isn't displaying the correct value when displayed

I am trying to increase the correct answer count by 1 every time the users answer is correct. However, when parsed into the display_result() function, the correct function displays "0 correct"
I haven't been able to get this working no matter how I try to wiggle around it, so any help is really appreciated.
code removed for academic integrity
If the user has answered 1 of 3 questions correctly, I expect the answer to be "You have answer 1 questions out of 3 correctly."
Currently, it would display you have answered 0 questions out of 3 correctly"
In menu_option() you never modify count, so it stays at 0. Two simple fixes. Change to:
count = check_solution(user_solution, real_solution, count)
return count
Or just
return check_solution(user_solution, real_solution, count)
One other thing I noticed: in get_user_input() you need to return the result of the recursive calls:
else:
print("Invalid input, please try again")
return get_user_input()
There are a number of problems:
you are doing correct = menu_option(option, correct) when instead you should be accumulating the correct scores like correct +=
in the menu_option you are never assigning to count, I presume it should be count = check_solution(...)
you shouldn't do return option for index == 5 because that will add to the correct.
Finally the code run as I expected(python3.6+ is required):
#!/usr/bin/env python3
import random
def get_user_input():
while True:
try:
index = int(input("Enter your choice: "))
if 0 < index < 6:
return index
except ValueError:
print("Invalid input, should be Integer.\n")
else:
print("Invalid input, please try again")
def get_user_solution(problem):
while True:
print("Enter your answer")
user_solution = input(f"{problem} = ")
try:
return float(user_solution)
except ValueError:
print("Invalid input, should be float\n")
def check_solution(user_solution, solution, count):
if user_solution == solution:
print("Correct.")
return count + 1
else:
print("Incorrect.")
return count
def menu_option(index, count):
first_num = random.randrange(1, 21)
second_num = random.randrange(1, 21)
if index == 1:
problem = f"{first_num} + {second_num}"
real_solution = first_num + second_num
print(real_solution)
user_solution = get_user_solution(problem)
return check_solution(user_solution, real_solution, count)
if index == 2:
problem = f"{first_num} - {second_num}"
real_solution = first_num - second_num
print(real_solution)
user_solution = get_user_solution(problem)
return check_solution(user_solution, real_solution, count)
if index == 3:
# blah blah blah, repeated code but removed for neatness
pass
if index == 5:
option = 5
return option
def display_result(total, correct):
if total == 0:
print("You answered 0 questions with 0 correct")
print("Your score is 0.0%")
else:
percentage = round(correct / total * 100, 2)
print(
f'You answered {total} questions with {correct} correct.\n'
f'Your score is {percentage}%'
)
def display_intro():
pass
def display_menu():
pass
def display_separator():
print('-'*20)
def main():
display_intro()
display_menu()
display_separator()
option = get_user_input()
total = 0
correct = 0
while option != 5:
total = total + 1
correct = menu_option(option, correct)
option = get_user_input()
print("Exit the quiz.")
display_separator()
display_result(total, correct)
if __name__ == "__main__":
main()

Average of a nested dictionary

I have a nested dictionary for a grade-book program that looks like this(this is just an example, it could be any number of students or tests):
workDictionary = {'kevin': {'Test1': 97, 'Test2': 84, 'Test3': 89},
''Bob':{'Test1': 67, 'Test2': 74, 'Test3': 59},
'carol':{'Test1': 47, 'Test2': 94, 'Test3': 79},
'ted':{'Test1': 67, 'Test2': 64, 'Test3': 99}}
And I want to get the average of the innermost values, for instance:
finalGrade = {}
for k,v in workDictionary.iteritems():
finalGrade[k] = sum(v)/ float(len(v))
There are other factors however, i'm using pickling and an undefined amount of students and tests. This is the full program:
# Modules
import pickle
def dumpPickle(fileName):
pickle.dump(workDictionary, open(fileName,'wb'))
return
def loadUnPickle(fileName):
global workDictionary
workDictionary = pickle.load(open(fileName, 'rb'))
return(workDictionary)
workDictionary = {}
keys = workDictionary.keys()
values = workDictionary.values()
def myMenu():
mySelect = -1
while mySelect != 0:
print("\n1. Open Dictionary File\n"+
"2. Create/Write to a Dictionary\n"+
"3. Add a New Student\n"+
"4. Find a Student's Scores\n"+
"5. Add a New Student Score\n"+
"6. Display Dictionary Data\n"+
"0. Exit\n"
)
mySelect = int(input("Enter Menu Number: "))
if mySelect == 1:
fileName = input("Enter file name")
print("\nyour file is now open")
loadUnPickle(fileName)
elif mySelect == 2:
fileName = input("please create a new file.")
print("\nyour new file is now open")
elif mySelect == 3:
newStudent = input("Enter the new student's name")
firstTest = input("Enter the name of the first test")
testGrade = input("Enter the new student's first grade")
addDictionary = {newStudent:{firstTest:testGrade}}
workDictionary.update(addDictionary)
print("\n" + newStudent + str(workDictionary[newStudent]))
dumpPickle(fileName)
elif mySelect == 4:
print("\nEnter student name")
myName = input()
for name in workDictionary:
if name == myName:
print("\n",workDictionary.get(myName))
elif mySelect == 5:
print("\nEnter student name ")
myName = input()
print("\nEnter assignment to add or update")
myValue = input()
for name in workDictionary:
if name == myName:
newGrade = input("Enter new Grade")
workDictionary[name][myValue]= newGrade
dumpPickle(fileName)
print("\n" + name + str(workDictionary[name]))
elif mySelect == 6:
print(workDictionary)
return
# Main Loop
I want to add another menu selection that takes the average of a certain student and displays it.
This is what i wrote, but you can rewrite it so it would fir better in your program:
def student_avg(student):
summ = 0
grades_num = 0
for test, grade in student.items():
summ += grade
# unless you aren't sure that grade would be a int, in which case add exception
grades_num += 1
average = summ / grades_num
return average
average = student_avg(workDict["kevin"])
You can use a Dict Comprehension
from statistics import mean
avg_grades = {name: mean(tests.values()) for (name, tests) in workDictionary.items()}
The result stored in avg_grades will be:
{'Bob': 66.66666666666667,
'carol': 73.33333333333333,
'kevin': 90.0,
'ted': 76.66666666666667}

I am unable to find the source of a UnboundLocalError for one of my variables

I am getting an error in my program, but I don't see the problem. The purpose of the program is display the menu and ask the user to choose a type of item and the quantity of the item. Then it will display the subtotal and the the total of it. But i know i messed up in the subtotal part, i might need help with that too if you can :D
Here is the error:
Traceback (most recent call last):
File "F:\COP1000\Classwork\Lab5\Lab5_6 YumYum Joint.py", line 70, in <module>
main()
File "F:\COP1000\Classwork\Lab5\Lab5_6 YumYum Joint.py", line 15, in main
total = calcTotal(subTotal, printItems)
File "F:\COP1000\Classwork\Lab5\Lab5_6 YumYum Joint.py", line 63, in calcTotal
return total
UnboundLocalError: local variable 'total' referenced before assignment
Here is the code:
def main():
endProgram ="no"
while endProgram =="no":
print()
print("Welcome to the burger place")
printItems = print_items()
yumBurger = getYum(printItems)
greaseFries = getFries(printItems)
sodaYum = getSoda(printItems)
subTotal = getSub(printItems, yumBurger, greaseFries, sodaYum)
total = calcTotal(subTotal, printItems)
print_info(yumBurger, greaseFries, sodaYum, total, subTotal)
endProgram = input("Do you want to end the program")
def print_items():
print ("Enter 1 for Yum Yum Burger")
print ("Enter 2 for Grease Yum Fries")
print ("Enter 3 for soda Yum")
printItems =int(input("Which burger will you like"))
return printItems
def getYum(printItems):
yumBurgers =0
if (printItems ==1):
yumBurger = int(input("How many burgers will you like: "))
return yumBurger
def getFries(printItems):
greaseFries =0
if (printItems ==2):
greaseFries =int(input("How many fries will you like: "))
return greaseFries
def getSoda(printItems):
sodaYum =0
if (printItems ==3):
sodaYum =int(input("How many sodas will you like"))
else:
print("Error")
return sodaYum
def getSub(printItems, yumBurger, greaseFries, sodaYum):
if printItems ==1:
subTotal = (yumBurger *.99)
elif printItems ==2:
subTotal = (greaseFries *.79)
elif printItems ==3:
subTotal = (sodaYum *1.09)
else:
print("Error")
return subTotal
def calcTotal(printItems, subTotal):
if printItems ==1:
total = (subTotal * .06) + subTotal
elif printItems ==2:
total = (subTotal * .06) + subTotal
elif printItems ==3:
total = (subTotal * .06) + subTotal
else:
print("Error")
return total
def print_info(yumBurger, greaseFries, sodaYum, total, subTotal):
print ("You orderd",yumBurgers," burgers")
print ("You ordered",greaseFries," fries")
print ("You ordered",sodaYum," sodas")
print ("The total is",total)
print ("The subtotal is",subTotal)
main()
This is what you meant
def getFries(printItems):
greaseFries = 0 # set default value here
if (printItems == 2):
greaseFries = int(input("How many fries will you like: "))
return greaseFries
You have to declare / initialize the variable greaseFries before it is used through the body of the function. In your existing code, when printItems isn't 2, the variable greaseFries won't be declared.
It's a good practice to declare/initalize your variable before using them.

Categories

Resources