'Not defined' when using subroutine - python

I'm trying to call the "name" under 'create():' in 'show():', but it says it's not defined. How can I save my input in 'create():', so I can use it in the other subroutines (in 'show():' for this example).
Thank you
I have tried to ask the user input after the choice part, but it doesn't solve it. I keep getting the same error.
import sys
class data:
name = ""
average = ""
def menu():
print("1) Data input")
print("2) Print data")
print("3) Give file name")
print("4) Save")
print("5) Read file")
print("0) Stop")
choice = int(input("Give your choice: "))
print()
return choice
def save(datalist, namea):
f = open(namea, "w")
for data in datalist:
row = str("{};{}").format(data.name, data.average)
f.write(row)
f.write("\n")
f.close()
def read(datalist, namea):
f = open(namea, "r")
for row in f:
row = row.split(";")
dataa = data()
dataa.name = str(row[0])
dataa.average = float(row[1])
datalist.append(dataa)
return datalist
def printt(datalist):
for data in datalist:
print(data.name, data.average)
def name():
namea = str(input("Give a name: "))
return namea
def inputt(datalist):
dataa = data()
dataa.name = str(input("Give a name: "))
dataa.average = float(input("Give the average (float): "))
datalist.append(dataa)
print()
return(datalist)
def main():
try:
datalist = []
while True:
choice = menu()
if (choice == 1):
datalist = inputt(datalist)
elif (choice == 2):
printt(datalist)
elif (choice == 3):
namea = name()
elif (choice == 4):
save(datalist, namea)
elif (choice == 5):
datalist = read(datalist, namea)
elif (choice == 0):
print("The program was closed {} at {}".format(datetime.datetime.now().strftime('%d.%m.%Y'), datetime.datetime.now().strftime('%H:%M:%S')))
return False
except Exception:
sys.exit(0)
main()
I excpect it to print the name I input in 1), when I call 2).
For example:
choice 1)
1) Give name: Daniel
choice 2)
2) Prints: Hello Daniel

you got a problem with your Scope.
The name variable is only local.
See https://www.programiz.com/python-programming/global-local-nonlocal-variables for more Information.
a hotfix would be using global-variables instead, or as Aaron D. Rodriguez suggested passing the name as parameter to the show-function.
def lista():
print("1) Write name.")
print("2) Print written name.")
print("0) Stop.")
choice = int(input("Give your choice: "))
return choice
def create():
global name
name = input("Give name: ")
return(name)
def show():
global name
print(name)
return
def main():
print("Choose from the following list:")
while True:
choice = lista()
if (choice == 0):
print("Thanks for using the program!")
break
elif (choice == 1):
create()
elif (choice == 2):
show()
else:
print("Input not detected.\nStopping.")
break
main()

You would have to have show() include a parameter in it. For example:
def show(n):
print(n)
So that when you call show(n), it prints whatever you include as n.
So if you called show(name). It would print out name.
def show(n):
print(n)
show(name) #This would print out name.
You also don't need return unless you are returning a value. Return doesn't make the code go back, it just makes the function return a value. So you do need return for list() and create(), but not for show(n).
Edit
You also would want to set the user input as a variable when you call create.
def main():
print("Choose from the following list:")
while True:
choice = lista()
if (choice == 0):
print("Thanks for using the program!")
break
elif (choice == 1):
name = create() #Here is where you should change it
elif (choice == 2):
show(name)
else:
print("Input not detected.\nStopping.")
break

Related

UnboundLocalError while accessing option 2 in a choice menu

I have been trying different code combinations for three days now and I figured before i throw in the towel this might be a good place to ask my question. In my code, no matter how I try to declare the lists I've been unsuccessful. My problem currently is:
line 54, in main
inputExpenseAmounts(expenseItems)
UnboundLocalError: local variable 'expenseItems' referenced before assignment
import matplotlib.pyplot as plt
from prettytable import PrettyTable
def menu():
print('[1] Enter Expense Name')
print('[2] Enter Expense Amount')
print('[3] Display Expense Report')
print('[4] Quit')
choice = input('Enter choice: ')
return choice
def inputExpenseNames():
expenseItems = []
name = input("Enter expense name (q for quit) \n")
while name != "q" :
expenseItems.append(name)
name = input("Enter expense name (q for quit) \n")
return expenseItems
def inputExpenseAmounts(expenseItems):
expenseAmounts = []
print("Enter the amount for each expense ")
for i in expenseItems:
amount = int(input(i + " : "))
expenseAmounts.append(amount)
return ExpenseAmounts
def displayExpenseReport(expenseItems, expenseAmounts):
displayExpenseReport = []
option = input("Display in \n (a) table \n (b) bar chart \n (c) pie chart \n")
if option == "c":
plt.pie(expenseAmounts, labels = expenseItems)
plt.show()
elif option == "b":
plt.bar(expenseItems, expenseAmounts)
plt.show()
elif option == "a":
t = PrettyTable()
t.add_column("expenseItems",expenseItems)
t.add_column("expenseAmounts",expenseAmounts)
print(t)
else:
print("Invalid option - allowed only (a / b / c")
def main():
while True:
choice = menu()
if choice == '1':
inputExpenseNames()
elif choice == '2':
inputExpenseAmounts(expenseItems)
elif choice == '3':
displayExpenseReport(expenseItems, expenseAmounts)
elif choice == '4':
break
else:
print('Invalid selection. Please re-enter.')
expenseItems = inputExpenseNames()
main()
The error is telling you that you used a variable (expenseItems) that hadn't been defined yet.
What you probably want to do is initialize those variables to empty lists, and then store the results of calling your earlier menu functions so you can pass them to the later functions.
def main():
expenseItems = []
expenseAmounts = []
while True:
choice = menu()
if choice == '1':
expenseItems = inputExpenseNames()
elif choice == '2':
expenseAmounts = inputExpenseAmounts(expenseItems)
elif choice == '3':
displayExpenseReport(expenseItems, expenseAmounts)
elif choice == '4':
break
else:
print('Invalid selection. Please re-enter.')
I'll note that you may want to rethink the idea of having a menu here, since the user always must go through the items in the exact order they're listed. It would be simpler to just automatically go through the three steps in order.

python array count each elements

I want a small program to count each part numbers enter by user.
here is so far I can do.
Is there a way I can export part numbers and their frequency to .csv file?
from collections import Counter
thislist = []
frequency = []
partnumber = ""
def mainmanu():
print ("1. Create List")
print ("2. Print list")
print ("3. Exit")
while True:
try:
selection = int (input("Enter Choice: ")
if selection ==1:
creatlist(thislist)
elif selection ==2:
counteach(thislist)
elif selection ==3:
break
except ValueError:
print ("invalid Choice. Enter 1-3")
def creatlist(thislist)
# while True:
partnumber = input ("Enter Part number: ")
if partnumber =="end":
print(thislist)
mainmanu()
break
thislist.append(partnumber)
def counteach(thislist)
Counter(thislist)
mainmanu()
mainmanu()
Welcome to the StackOverflow.
You are calling the mainmanu function inside another function which is called by mainmanu function. Instead what you should be doing is letting mainmanu calling all the other helper functions. Antoher thing, you can't call break in another function and expect where it is called to break.
The execution goes like this:
mainmanu is called, it calls creatlist, after it finishes execution it continues to execute the instructions where it is left from.
from collections import Counter
thislist = []
frequency = []
partnumber = ""
def mainmanu():
print ("1. Create List")
print ("2. Print list")
print ("3. Exit")
while True:
try:
selection = int (input("Enter Choice: ")
if selection ==1:
if creatlist(thislist): # line x
break
elif selection ==2:
counteach(thislist)
elif selection ==3:
break
except ValueError:
print ("invalid Choice. Enter 1-3")
def creatlist(thislist)
# while True:
partnumber = input ("Enter Part number: ")
if partnumber =="end":
print(thislist)
return True #this value will make the the condition to be true see line x
thislist.append(partnumber)
return false
def counteach(thislist)
Counter(thislist)
mainmanu()

Python Coursework tidying

I need help with a one or two things on my coursework. firstly when I input an incorrect username/password it will output more than one error message at a time. Secondly, when the men function ends the program will go back to the login loop( that allows the user to re-enter their username/password), I have fixed this by using the B variable but this feels extremely janky and I know there is a better way of doing it. Any Modifications or Tips are greatly appreciated (even if they're not related to my above problems). also the way i code is a bit weird so it's probs best you read from bottom to top :)
def quiz():
print ("quiz")# place holder for real code (let's me know the function has been run)
def report():
print ("report") # place holder for real code (let's me know the function has been run)
def a_menu():# Admin menu
print ("Welcome to the student quiz!")
print ("Please choose a option")
while True:
print ("1: Computer science")
print ("2: Histroy")
print ("3: Reports")
menu_in = int(input())
if menu_in == 1:
Comp_sci = True
quiz()
break
elif menu_in == 2:
Hist = True
quiz()
break
elif menu_in == 3:
report()
break
else:
print ("Invalid input! Please try again..")
def menu():
print ("Welcome to the student quiz!")
print ("Please choose a quiz")
while True:
print ("1: Computer science")
print ("2: Histroy")
menu_in = int(input())
if menu_in == 1:
Comp_sci = True
quiz()
break
elif menu_in == 2:
Hist = True
quiz()
break
def login():
b = False
print ("Please enter your username and password")
while True:
if b == True:
break
log_user = input("Username:")
log_pass = input ("Password:")
with open("D:\\Computer science\\Computing test\\logindata.txt","r") as log_read:
num_lines = sum(1 for line in open('D:\\Computer science\\Computing test\\logindata.txt'))
num_lines = num_lines-1
for line in log_read:
log_line = log_read.readline()
log_splt = log_line.split(",")
if log_user == log_splt[0] and log_pass == log_splt[2]:
if log_splt[5] == "a": # Admin will have to mannually change the admin status of other user's through .txt file.
b = True
a_menu()
else:
b = True
log_read.close()
menu()
break
else:
print ("Incorrect username or password, please try again!")
def register():
print ("enter your name, age, and year group and password")
while True:
reg_name = input("Name:")
reg_pass = input ("Password:")
reg_age = input ("age:")
reg_group = input ("Year Group:")
print ("Is this infomation correct?")
print ("Name:",reg_name)
print ("password:",reg_pass)
print ("Age:",reg_age)
print ("Year Group:", reg_group)
reg_correct = input ("[Y/N]").lower()
if reg_correct == "y":
reg_user = reg_name[0:3]+reg_age
reg_write = open("D:\\Computer science\\Computing test\\logindata.txt","a")
reg_write.write (reg_user+","+reg_name+","+reg_pass+","+reg_age+","+reg_group+","+"u"+"\n")
print ("Your username is:",reg_user)
reg_write.close()
login()
break
elif reg_correct == "n":
print ("Please Re-enter your infomation")
else:
Print ("Invalid input! Please try again...!")
def login_ask():
print ("Do you already have an account?")
while True:
ask_in = input("[Y/N]").lower()
if ask_in == "y":
login()
break
elif ask_in == "n":
register()
break
login_ask()

Python: Validating earlier in the code

This is my code which is a quiz for children. What I need help on is, after the code asks the user for its class, it should validates whether the input is valid or not straight away instead of doing it in the end and displaying the message
"Sorry, we can not save your data as the class you entered is not valid."
I've tried moving the whole if, elif, and else statements to straight after:
users_class = int(input("Which class are you in? (1,2 or 3)"))
But that doesn't help. Any help will be appreciated :)
import time
import random
import math
import operator as op
def test():
num1 = random.randint(1, 10)
num2 = random.randint(1, num1)
ops = {
'+': op.add,
'-': op.sub,
'*': op.mul,
}
keys = list(ops.keys())
rand_key = random.choice(keys)
operation = ops[rand_key]
correct_result = operation(num1, num2)
print ("What is {} {} {}?".format(num1, rand_key, num2))
user_answer= int(input("Your answer: "))
if user_answer != correct_result:
print ("Incorrect. The right answer is {}".format(correct_result))
return False
else:
print("Correct!")
return True
username=input("What is your name?")
print ("Hi {}! Wellcome to the Arithmetic quiz...".format(username))
users_class = int(input("Which class are you in? (1,2 or 3)"))
input("Press Enter to Start...")
start = time.time()
correct_answers = 0
num_questions = 10
for i in range(num_questions):
if test():
correct_answers +=1
print("{}: You got {}/{} {} correct.".format(username, correct_answers, num_questions,
'question' if (correct_answers==1) else 'questions'))
end = time.time()
etime = end - start
timeTaken = round(etime)
print ("You completed the quiz in {} seconds.".format(timeTaken))
if users_class == 1:
with open("class1.txt","a+") as f:
f.write(" {}:Scored {} in {} seconds.".format(username,correct_answers,timeTaken))
elif users_class == 2:
with open("class2.txt","a+") as f:
f.write(" {}:Scored {} in {} seconds.".format(username,correct_answers,timeTaken))
elif users_class == 3:
with open("class3.txt","a+") as f:
f.write(" {}:Scored {} in {} seconds.".format(username,correct_answers,timeTaken))
else:
print("Sorry, we can not save your data as the class you entered is not valid.")
You should check that the input is valid immediately after the input, something like this:
import sys
users_class = int(input("Which class are you in? (1,2 or 3)"))
if users_class not in {1,2,3}:
print("Sorry, you must enter either a 1, 2, or 3!")
sys.exit(1)
Note that the sys.exit(1) call will exit the program.
Now, this isn't the most robust way to do things. If the user inputs something other than a number, for example, int(...) will raise an exception, because it can't convert, say, "dog", to an integer. Furthermore, you might prefer that the program continue asking for valid input, rather than just stopping and exiting. Here's some code that will do just that:
while True:
try:
# try to convert the user's input to an integer
users_class = int(input("Which class are you in? (1,2 or 3)"))
except ValueError:
# oh no!, the user didn't give us something that could be converted
# to an int!
print("Please enter a number!")
else:
# Ok, we have an integer... is it 1, 2, or 3?
if users_class not in {1,2,3}:
print("Please enter a number in {1,2,3}!")
else:
# the input was 1,2, or 3! break out of the infinite while...
break
print(users_class)
You just need to add an extra condition following the question about which class the user is in. Normally we would have a loop here so that the user is asked again if they enter an invalid response.
print ("Hi {}! Welcome to the Arithmetic quiz...".format(username))
while True:
users_class = int(input("Which class are you in? (1,2 or 3)"))
if users_class in [1, 2, 3]:
break
print('Please make sure you enter a class from 1 to 3')
You need to check whether the value is 1, 2 or 3 straight after you ask them, so, you can move the if's directly after the users_class = int(input("Which class are you in? (1,2 or 3)")).
Move the correct_answers=0 above the if's and set timeTaken to 0 before.
This works:
import time
import random
import math
import operator as op
import sys
def test():
num1 = random.randint(1, 10)
num2 = random.randint(1, num1)
ops = {
'+': op.add,
'-': op.sub,
'*': op.mul,
}
keys = list(ops.keys())
rand_key = random.choice(keys)
operation = ops[rand_key]
correct_result = operation(num1, num2)
print ("What is {} {} {}?".format(num1, rand_key, num2))
user_answer= int(input("Your answer: "))
if user_answer != correct_result:
print ("Incorrect. The right answer is {}".format(correct_result))
return False
else:
print("Correct!")
return True
username=input("What is your name?")
print ("Hi {}! Wellcome to the Arithmetic quiz...".format(username))
users_class = int(input("Which class are you in? (1,2 or 3)"))
correct_answers = 0
timeTaken = 0
if users_class == 1:
with open("class1.txt","a+") as f:
f.write(" {}:Scored {} in {} seconds.".format(username,correct_answers,timeTaken))
elif users_class == 2:
with open("class2.txt","a+") as f:
f.write(" {}:Scored {} in {} seconds.".format(username,correct_answers,timeTaken))
elif users_class == 3:
with open("class3.txt","a+") as f:
f.write(" {}:Scored {} in {} seconds.".format(username,correct_answers,timeTaken))
else:
print("Sorry, we can not save your data as the class you entered is not valid.")
sys.exit(0);
input("Press Enter to Start...")
start = time.time()
num_questions = 10
for i in range(num_questions):
if test():
correct_answers +=1
print("{}: You got {}/{} {} correct.".format(username, correct_answers, num_questions,
'question' if (correct_answers==1) else 'questions'))
end = time.time()
etime = end - start
timeTaken = round(etime)
print ("You completed the quiz in {} seconds.".format(timeTaken))
If it's invalid, then quit via sys, otherwise continue as your current code does.

Invalid syntax error on the elif statement

I'm writing this program that lets users choose an option to display, change,add, remove, write or quit
I keep getting invalid syntax error on this elif statement in my program and i dont know why?
DISPLAY = 'D'
CHANGE = 'C'
ADD = 'A'
REMOVE = 'R'
WRITE = 'W'
QUIT = 'Q'
#main function
def main ():
print()
print()
print('\t Wombat Valley Tennis Club')
print('\t Member Register')
print('\t =======================')
main_dic = {}
with open ('wvtc_data.txt','r')as x:
for line in x:
line = line.rstrip ('\n')
items = line.split (':')
key,value = items[0], items[1:]
main_dic[key] = values
choice = input('choice: ')
while choice != QUIT:
choice = get_menu_choice()
if choice==DISPLAY:
display(main_dic)
elif choice==CHANGE:
change(main_dic)
elif choice== REMOVE:
remove (main_dic)
elif choice==WRITE:
write(main_dic)
def get_menu_choice():
print()
print("\t\t Main Menu")
print()
print('\t<D>isplay member details')
print('\t<C>hange member details')
print('\t<A>dd a new member')
print('\t<R>emove a member')
print('\t<W>rite updated details to file')
print('\t<Q>uit')
print()
print('Your choice (D, C, A, R, W OR Q)?\t[Note: Only Uppercase]')
print()
choice = input("Enter your choice: ")
while choice < DISPLAY and choice < CHANGE or choice > QUIT:
choice = input ('Enter your choice: ')
return choice
def display(main_dic):
name = input('Type the name of the member:')
print()
print (main_dic.get(name, 'not found!'))
print()
print()
def change(main_dic):
name=input("Enter the member number")
print()
print(main_dic.get(name,'not found!'))
print()
NAME = 1
EMAIL = 2
PHONE = 3
print('Please select')
print('==============')
print('Change Name<1>')
print('Change E-mail<2>')
print('Change Phone Number<3>')
print()
if choose == NAME:
new_name = input('Enter the name: ')
print()
print("Data has been changed")
main_dic[name][0]=new_name
print (mem_info[name])
print()
elif choose == EMAIL:
new_email=input('Enter the new email address:')
print ('Email address has been changed')
#change the data
main_dic[name][1]=new_email
print(mem_info[name])
print()
elif choose == PHONE:
new_phone = int (input('Enter the new phone number'))
print ("phone number has been changed")
main_dic[name][2]=new_phone
print(main_dic[name])
print
def write(main_dic):
print()
name = input ("Enter the name of a member:")
print()
print (mem_info.get(name,'Not found!'))
print()
main()
main()
Also any help or suggestions in making this code work are appreciated.
It's a formatting problem. The elifs have to start in the same column as the if to which they belong.
Example
if something:
do_somtething()
elif something_else:
do_the_other_thing()

Categories