NameError: free variable 'addcontact' referenced before assignment in enclosing scope - python-3.x

please be kind with my n00b question but it is driving me crazy and googling it didn't help much unfortunately.
I am trying to write a simple phonebook script using an empty dictionary as a learning exercise but as I am self taught there is no one else to turn to.
So here's what's happening,
I want to write a menu function that includes subfunctions for adding, deleting and editing {name:number} contacts
it is mostly working except for when I try to call the add function from within the edit
this is part of the menu code including the add routine
def menu():
selection = (int(input("""1:View phonebook
2:Add contact
3:Delete contact
4:Search for a contact and if necessary edit it
5:Save and Exit
What would you like to to?""")))
if selection == 1:
if len(phonebook)== 0:
print("Phonebook is empty, please add a contact first.")
loop = input("Press Enter to continue ...")
menu()
else:
print(phonebook)
loop = input("Press Enter to continue ...")
menu()
elif selection == 2:
def addcontact():
first = (str(input("First name: ")))
last = (str(input("Last name: ")))
num = (str(input("Number? ")))
phonebook.update({last + " " + first: num})
loop = input("Contact saved, press Enter to continue.")
menu()
(other stuff...)
menu()
and this is the update subroutine that's giving me trouble
elif selection == 4:
def search_and_edit():
search = (str(input("Please type the exact name of the contact you are looking for: ")))
if search in phonebook.keys():
print("Name: ", search, "Number: ", phonebook[search])
edit = (str(input("Do you wish to edit this contact? Y/N")))
if edit == "N" or edit == "n":
menu()
if edit == "Y" or edit == "y":
phonebook.pop(search)
addcontact()
else:
print("Contact not found.")
loop = input("Press Enter to continue.")
menu()
and this is the error message from PyCharm
File "C:\Users\Derek\PycharmProjects\pythonProject\phonebook\phonebook.py", line 78, in search_and_edit
addcontact()
NameError: free variable 'addcontact' referenced before assignment in enclosing scope
Process finished with exit code 1
what am I doing wrong here? the other callbacks work fine ("loop" callbacks to return to the main menu for example) but the addcontact() one fails with a variable error message even though it's a function

welcome aboard. The issue boils down to the addcontact being defined within the scope of a conditional (if...elif...else) and as a result not visible to search_and_edit which is defined in a different and mutually exclusive branch. So, when you chose 4, the program hadn't really entered 2 and the addcontact had not been "created" yet.
If you wish to make a function available at multiple places, then define it where it would in scope for all the callers.

Related

Unreachable code in if statement inside a while loop

I was trying to make a menu with a while loop to keep repeating until a valid input was entered. This is the code that I have:
print("1) Play game")
print("")
print("2) Instructions")
print("")
print("3) Quit")
print("")
while True:
try:
menu = int(input("Make a selection: "))
except ValueError:
print("Sorry, your input was not valid")
continue
if menu > 3 or menu < 1:
print("Please use a number in the range 1-3")
continue
else:
break
if menu == 1:
print("Lets go!")
elif menu == 2:
print("Lets go!")
else:
print("Quitting...")
The "if" where it says "if menu > 3 or menu < 1:" gives an error saying that:
"Unreachable codepylint(unreachable)"
Please help, it would be much appreciated.
Problem 1: continue statement
To help you understand your code, i used a flowchart to draw the lines for you.
However, if you move the continue inside the except statement, then the code will pass onto the if statement on a successful try statement.
The challenge is, that the code is never going into the if menu > 3.... statement, it always goes to try or except and then does the continue. So its looping itself skipping the if menu > 3 .... statement. That means, you never get out of the loop as it never gets to execute break.
Problem 2: You said you removed the continue statement.
When you remove continue from the statement, you create a new problem. If the code goes into except clause, variable menu did not get created properly. So when it goes to if menu > 3 ..., the variable has not been defined (due to except clause), and that gives you a new error.
Solution:
I would recommend to move the continue statement inside the except clause. That will take care of the problem. It will go back to while statement if there is an error with the input for menu. If it is successful, then your if menu > 3 ... will execute properly.
The modified correct code will be:
while True:
try:
menu = int(input("Make a selection: "))
except ValueError:
print("Sorry, your input was not valid")
continue #move this inside except
if menu > 3 or menu < 1:
print("Please use a number in the range 1-3")
continue
else:
break
if menu == 1:
print("Lets go!")
elif menu == 2:
print("Lets go!")
else:
print("Quitting...")

Python 3 How to Ask user for specific input and reject invalid inputs

I have a question on how to check a user's input and make sure they are returning a specific string. Currently, the function when called will ask the user for their input. However, if they choose a string that is not part of the function, the else statement will execute and continue the code. I am trying to figure out how to loop this function, until a user inputs one of the strings that the function is looking for. Can anyone help me with this? I am new to python and would appreciate any help.
def dwarf_class_definer(dwarf_class):
if dwarf_class == "Thane":
print("'Ahhh Nobility'")
elif dwarf_class == "Mekanik":
print("'Interesting a Mechanic'")
elif dwarf_class == "Ancestrite":
print("'A spiritualist. I see...'")
elif dwarf_class == "Prisoner":
print("'Never met a gen-u-ine 'Last chancer.'")
elif dwarf_class == "Civilian":
print("'ehhh a civilian? Wut you doing here?'")
else:
print("You aren't choosing a valid class.")
dwarf_class = input("Which Class will you choose?: ")
dwarf_class_definer(dwarf_class)
A while loop will keep going until you tell it not to anymore. You can see when an expected value is supplied, the break command will terminate the while loop. A dictionary can also make your code a lot cleaner and easier to maintain compared to a bunch of if statements.
dwarf_classes = {
"Thane": "'Ahhh Nobility'",
"Mekanik": "'Interesting a Mechanic'",
"Ancestrite": "'A spiritualist. I see...'",
"Prisoner": "'Never met a gen-u-ine 'Last chancer.'",
"Civilian": "'ehhh a civilian? Wut you doing here?'",
}
while True:
dwarf_class = input("Which Class will you choose?: ")
if dwarf_class in dwarf_classes.keys():
print(dwarf_classes[dwarf_class])
break
print("You aren't choosing a valid class.")
example:
$ python3 so.py
Which Class will you choose?: Python!
You aren't choosing a valid class.
Which Class will you choose?: Prisoner
'Never met a gen-u-ine 'Last chancer.'

Python 3 Jump Tables

I am trying to figure out how to create a basic jump table, so I can better understand different ways of creating menus in Python 3.5.6. Here is what I have so far:
def command():
selection = input("Please enter your selection: ")
return selection
def one():
print ("you have selected menu option one")
def two():
print ("you have selected menu option two")
def three():
print ("you have selected menu option three")
def runCommand(command):
jumpTable = 0
jumpTable[command]()
jumpTable = {}
jumpTable['1'] = one
jumpTable['2'] = two
jumpTable['3'] = three
def main():
command()
runCommand(command)
if __name__ == "__main__":
main()
As far as I understand, a jump table is simply a way of making a menu selection and calling a specific function associated with that numerical value, taken in by my "command" function. Within the jumpTable, you assign the function to call.
I am getting " File "omitted", line 16, in runCommandjumpTableone
TypeError: 'int' object is not subscriptable
All I want to do is have the user enter a number - 1, 2 or 3 and have that function run. when I get this basic functionality down, I will expand the menu to show the options and be more clear. I just need to get the darn thing to run!
Yes, I am aware of other ways to create menus (IF/ELIF/ELSE) I am just trying to nail this one down!
Thank you in advance!
You are quite close. The only issue is that you are trying to access the command before creating the jumpTable. And I am also not sure why you are setting the variable to 0 first (that's why you get the int is not subscriptible error). So, this is the right order:
def runCommand(command):
jumpTable = {}
jumpTable['1'] = one
jumpTable['2'] = two
jumpTable['3'] = three
jumpTable[command]()
By the way, if you are always creating the same jumpTable, you could create it once, outside the function and simply call jumpTable[command]() in your main function.
Another problem: you should store the value you get from the user and pass that to the next function like this:
cmd = command()
runCommand(cmd)
, or simply pipe the two functions together like this:
runCommand(command())
"""
Based on the original question, the following will.
Add a menu to a console application to manage activities.
Run a selected function.
Clear the output
Display the menu again or exit if done is selected
"""
import sys
from os import system
def display_menu(menu):
"""
Display a menu where the key identifies the name of a function.
:param menu: dictionary, key identifies a value which is a function name
:return:
"""
for k, function in menu.items():
print(k, function.__name__)
def one():
print("you have selected menu option one")
input("Press any Enter to return to menu.")
system('cls') # clears stdout
def two():
print("you have selected menu option two")
input("Press any Enter to return to menu.")
system('cls') # clears stdout
def three():
print("you have selected menu option three")
input("Press any Enter to return to menu.")
system('cls') # clears stdout
def done():
system('cls') # clears stdout
print("Goodbye")
sys.exit()
def main():
# Create a menu dictionary where the key is an integer number and the
# value is a function name.
functions_names = [one, two, three, done]
menu_items = dict(enumerate(functions_names, start=1))
while True:
display_menu(menu_items)
selection = int(
input("Please enter your selection number: ")) # Get function name
selected_value = menu_items[selection] # Gets the function name
selected_value() # add parentheses to call the function
if __name__ == "__main__":
main()

How to edit strings in a list

What I want is this - I have a list of names created from user input. now i have to come up with a way for the user to edit a name by entering the name that they what to edit and then obviously edit it into what they want and store it in the list.
if it helps heres everything I have so far. def edit() is where im struggling.
def mainMenu():
print("\nMAIN MENU")
print("1. Display Members:")
print("2. Add A Member(s):")
print("3. Remove A Member:")
print("4. Edit Member:")
print("5. Exit:")
selection = int(input("\nEnter Choice: "))
if selection == 1:
display()
elif selection == 2:
add()
elif selection == 3:
remove()
elif selection == 4:
edit()
elif selection == 5:
exit()
else:
print("Invalid choice, enter 1-5.")
mainMenu()
def display():
#displaying roster...
print(roster)
mainMenu()
def add():
#adding team members...
size = int(input("How many players are you adding?"))
global roster
roster = [0] * size
for i in range(size):
roster[i] = input("Enter members name: ")
roster.append(roster)
mainMenu()
def remove():
#removing a team member...
roster.remove(input("Enter member to be removed: "))
mainMenu()
def edit():
#edit a team member...
roster.insert(input("Enter Name to be edited: "))
mainMenu()
mainMenu()
Removing and adding elements are pretty easy in python because they are directly supported by the language. Each of them can be translated into only one instruction.
When something doesn't seem very obvious, such as the editing functionality you are trying to implement, try breaking it down to things that can be expressed as a simple operation that holds one one line (even if not in order).
To find the answer I thought this: somewhere in my code, I want to type roster[ind_name_to_edit] = new_name.
I knew then that before typing this, I would want to find the value of ind_name_to_edit. This can be done by roster.index(name_to_edit). And you already know how to get the name to be edited and the name to edit ;)
If you're still unsure how to do what you want to do, re-read this answer and see the documentation of the index method of list in python3 and maybe some examples here.
N.B: If your list is supposed to be sorted in some way, you should implement your own search algorithm instead of using index, and you should consider re-sorting the list after the edit. I know it's a long shot but just in case.

why doesn't the highlighted section of code work and what do i need to change to make it able to work

I just deleted my previous question as someone made it embarrassingly obvious that I didn't ask an actual question with a main goal.I apologise for this.
I am only referring to the last part of the code. The "A" option as i cannot figure out why it is incorrect
The full thing works other than the A section it says there is a syntax error. That's it.
I've tried re placing the brackets and playing around with them and so on.
def Jobs():
def Parse_Line(Job_Line):
Job_Line = Job_Line.strip()
Estimate_Number, Estimate_Date, Customer_ID, Final_Total, Job_Status,Amount_Pay= Job_Line.split(",")
Painting_Job = {
'Estimate_Number':Estimate_Number,
'Estimate_Date':Estimate_Date,
'Customer_ID':Customer_ID,
'Final_Total':Final_Total,
'Job_Status':Job_Status,
'Amount_Pay':Amount_Pay,
}
return Painting_Job
Job_List = []
with open("paintingJobs.txt", "r") as Painting_Jobs:
for line in Painting_Jobs:
Job_List.append(Parse_Line(line))
return Job_List
def Accepted(job):
return job['Job_Status'] == "A"
def Outstanding(job):
return int(job['Final_Total']) - int(job['Amount_Pay'])
Job_List = Jobs()
print ("\nOption A: Search for an estimate\n\nOption B: Dislay the outstanding payments\n\nOption C: Display your total revenue\n\nOr Press Q to quit")
Option_Choice = input("Which option do you want to do?")
if Option_Choice == "A" or Option_Choice == "a":
Estimate_no = input("Please enter the required estimate number so we search our database: ")
Estimate_Found = Estimate_no
job in Job_List if ['Estimate_Number'] == Estimate_no
if Estimate_Found:
print (Estimate_Found)

Resources