UnboundLocalError While Trying to Call a Function - python

I'm doing an assignment that takes a number and tells the user if it is a valid SIN number. I can't get my program to run because of this:
UnboundLocalError: local variable 'isdigit' referenced before assignment.
How do I fix this?
from sinmodule import is_valid
def main():
print "SIN Validator"
print "============="
isdigit()
def isdigit():
int_str = str(sinnumber)
length = (len(int_str))
number = raw_input("Please Enter SIN (Q to quit):")
while length != 8:
print "You did not enter 'Q' or a number."
sinnumber = raw_input("Please Enter SIN (Q to quit):")
if length == 8:
if status == True:
print "The number",number," IS a valid SIN."
else:
print "The number",number,"is NOT a valid SIN."
if number == "Q":
print "Good-bye!"
main()

You shouldn't have any issues with UnboundLocalError on isdigit in your code. It is defined in one place, and called as a function inside of a second function. The rules of scoping apply.
However you have not defined the variable sinnumber by the time you use it:
def isdigit():
int_str = str(sinnumber) # <--- here this is unbound
length = (len(int_str))
number = raw_input("Please Enter SIN (Q to quit):")
while length != 8:
print "You did not enter 'Q' or a number."
sinnumber = raw_input("Please Enter SIN (Q to quit):") #<-defined here
...
You need to move the definition (in the while loop) to before you use it. Also, check to see how you're "growing" sinnumber, and where you're updating length

Related

How to prevent user from inputting spaces/nothing in Python?

I have a problem in which users can input spaces or nothing and still pass through the program, how do I go about preventing this? I am still a beginner at python.
def orderFunction(): # The function which allows the customer to choose delivery or pickup
global deliveryPickup
deliveryPickup = input("Please input delivery or pickup: d for delivery p for pickup")
if deliveryPickup == "d":
global customerName
while True:
try:
customerName = (input("Please input your name"))
if customerName == (""):
print("Please input a valid name")
else:
break
global customerAddress
while True:
try:
customerAddress = (input("Please input your name"))
if customerAddress == (""):
print("Please input a valid Address")
else:
break
global customerPhnum
while True:
try:
customerPhnum = int(input("Please input your phone number"))
except ValueError:
print("Please input a valid phone number")
else:
break
print("There will also be a $3 delivery surcharge")
elif deliveryPickup == "p":
customerName = (input("Please input your name"))
if customerName == (""):
print("Please input a valid name")
orderFunction()
else:
print("Please ensure that you have chosen d for Delivery or p for Pickup")
orderFunction()
orderFunction()
Here is my attempt at doing this but I get all kinds of unindent and indent errors at the moment and I think my while loops are probably wrong.
Essentially if I input a space or hit enter into one of the customer inputs (customerName for instance) it gets stored. This needs to prevented and I have tried to fix it by using while loops which obviously haven't worked.
Hopefully someone has a solution to this problem
Many Thanks.
.strip() removes all tabs or spaces before and after a string.
Meaning all spaces == empty string. All tabs == empty string. So all you have to check if the length of that string != 0 or the string is not empty. Just use an infinite loop to keep on forcing the right input.
Also as a tip, you don't have to limit yourself into one function.
Here's a working code below.
def getNonBlankInput(message, error_message):
x = input(message)
while len(x.strip()) == 0:
x = input(error_message)
return x
def getValidIntegerInput(message, error_message):
msg = message
while(True):
try:
x = int(input(msg))
break
except ValueError:
msg = error_message
return x
def orderFunction(): # The function which allows the customer to choose delivery or pickup
global deliveryPickup
global customerName
global customerAddress
global customerPhnum
deliveryPickup = input("Please input delivery or pickup: d for delivery p for pickup")
if deliveryPickup == "d":
customerName = getNonBlankInput("Please input your name: ", "Please input a valid name: ")
customerAddress = getNonBlankInput("Please input your address: ", "Please input a valid address: ")
customerPhnum = getValidIntegerInput("Please input your phone number: ", "Please input a valid phone number: ")
print("There will also be a $3 delivery surcharge")
elif deliveryPickup == "p":
customerName = getNonBlankInput("Please input your name: ", "Please input a valid name: ")
else:
print("Please ensure that you have chosen d for Delivery or p for Pickup")
orderFunction()
orderFunction()
Try using a regular expression that checks if any character between "A-Z" has been inserted, if not, give an error
The while loops are a decent solution, you just need to add more checks to your if statements.
First, you don't need a try statement on the top two loops. Don't use a try statement unless you're expecting an error, which you need to handle with an except statement, like you do in the bottom while loop.
Then you just need to add more conditions to your top two loops, I don't know exactly what you want to prevent, but you could try checking the length of the input, also see this answer for an interesting method:
https://stackoverflow.com/a/2405300/8201979
Instead of using input right away you can make a function similar to this one that will only allow valid inputs.
You can use this valid_input function instead of input.
def valid_input(text):
not_valid = True
res = ''
while not_valid:
res = input(text)
if res.split(): # if text is empty or only spaces, this creates an empty list evaluated at False
not_valid = False
return res
here the check is pretty simple: every text made out of nothing or spaces won't be allowed and we will keep asking for the same input until a valid information is given.
I made this code simple just so you get a general idea. But you can change the validation test to your liking and maybe also output a warning saying why the input wasn't allowed so the person knows what to do. You can do more advanced validation with regex, and maybe you need a minimum text length etc...
You have indent error because you have a try statement without the corresponding except.
You need both to make it work (as you did in the Phone number section).
Here is a link to the try/except: docs
Also, you can check if a string is empty as detailed in this answer.
So for example you want to write:
try:
customerName = input("Please input your name")
if not customerName:
print("Please input a valid name")
else:
break
except ValueError:
print("Please input a valid name")
Although the above seems a bit redundant, so you might want to raise an exception if the customer name is empty, catch the exception in the except block, print the warning and return error (or something else).
try:
customerName = input("Please input your name")
if not customerName:
raise ValueError
except ValueError:
print("Please input a valid name")
else:
break
Try adding another while true for pick and delivery option so that it can prevent taking other inputs
you don't need any of those try/excepts (which are broken anyway).
Its difficult to figure out what you're trying to do, are you trying to raise an exception if an empty string is passed, or request another input from the user? You seem to be half implementing both at the moment.
If its the latter, something like this would work.
def func(fieldname):
while True:
val = input("Please input your {}".format(fieldname))
if val.strip() != "":
break
else:
print("Please input a valid {}".format(fieldname))
return val
delivery_pickup = input("Please input delivery or pickup: d for delivery p for pickup")
if delivery_pickup == "d":
customer_name = func("name")
address = func("address")
phone_number = func("phone number")
What you are looking for is the str.strip method that remove trailing whitespace in strings.
Also I think try is not particularly suited for your needs here.
customerName = input("Please input your name")
while not customerName.strip():
customerName = input("Please input a valid name")
for the phone number I would not convert to integer because if the phone number starts with zeros, they will not be stored.

How to create a function in Python?

I am new to coding and I am learning python. I’m trying to write a simple program to test my skills, but I’m having some difficulties with it; I want to turn it into a function in order to make the program cleaner, but I get this error: http://prntscr.com/im5pt7
Here is what I want to put inside a function:
name = input(str("\nFull Name: "))
position = input(str("Position at the company: "))
print("\nConfirm Staff Data:\n")
name_confirm = "Name: %s"%(name)
position_confirm = "Position: %s"%(position)
print(name_confirm)
print(position_confirm)
confirmAns = input("Is the information right? (Y/N)")
if confirmAns == "y" or confirmAns == "Y":
message = "\nSearching for %s"%(name)
print(message)
hoursWorked = int(input("Insert hours worked: "))
if hoursWorked <= 0:
print("Please insert a valid number")
elif hoursWorked > 0:
print("\nCalculete Paycheck")
hourRate = int(input("Insert the rate of each hour worked: "))
bonus = input("If a bonus was given insert it here: ")
fine = input("If a fine was given insert it here: ")
print('\n')
payment = hoursWorked*hourRate-int(fine)+int(bonus)
paymentMsg = "Your Payment is: $%d"%(payment)
print(paymentMsg)
elif confirmAns == "n" or confirmAns == "N":
ctypes.windll.user32.MessageBoxW(0, "The software will close to avoid slowness.", "Warning", 1)
else:
print("Please answer with Y or N")
I've tried this but it did not work.
Here is all the code (working but with out the function so I need to copy and paste code): https://pastebin.com/PA9mxMkk
What is happening is that the function as other statements needs to hold it's code into a new indentation level
print('a')
def test(var):
print(var)
not this way
print('a')
def test(var):
print(var)
because this way it will give you the error that you are seeing.
All python code should be indented after the ':' character, in python the indentation should be 4 spaces, or people use the tab key, your code has an issue with indentation which I can't be bothered finding;
for example a 'class'
class this_is_a_class():
#indentation
#code goes here
pass
or a 'for loop' or 'while loop';
numbers = [0,1,2,3,4,5,6,7,8,9]
for number in numbers:
#indentation
print(number)
x = 0
while x < 10:
#indentation
x += 1
print('This is going to print 10 times')
or an 'if statement';
true_boolean = True
if true_boolean:
#indentation
print(True)
or a 'function';
def function():
#indentation
print('You have called a function')
What is actually happening, is python is reading through your code 'Token' by token and 'interpreting' what your code does. But considering you don't know what a function is; gloss over this paragraph.
Now for your question about how functions work. A function is used organize code. You can call a function multiple times, which makes your code more organized and easier to work with, this is why as your code got longer, you ran into this problem; Lets for example say i wanted to print 'hello world' 10 times.
I could write this code on 10 seperate lines;
print("hello world")
print("hello world")
#etc... More chance for error
or I could use a function and call it 10 times;
def say_hello_world():
#indentation
print("hello world")
for each_call in range(0,10):
say_hello_world() #This is the function call
You can also pass 'arguments into a function' for example;
def say_hello(person):
#indentation
print('hello', person)
say_hello('Alex')
Now any words that are in quotations in this answer can be google searched with the word 'python' and you can find out much more about how python works.
I hope this gets you started with python. Although all of these concepts can be used in other programming languages.
The first step which is often difficult in learning python in understanding indentation.
for example.
def hello_world(world):
print("hello ", world)
#your function code goes here.
#you need to indent back to be out of function block.
hello_world("there!")
out: hello there
so in your case it should be like this.
def AnsNo():
name = input(str("\nFull Name: "))
position = input(str("Position at the company: "))
print("\nConfirm Staff Data:\n")
name_confirm = "Name: %s"%(name)
position_confirm = "Position: %s"%(position)
print(name_confirm)
print(position_confirm)
confirmAns = input("Is the information right? (Y/N)")
if confirmAns == "y" or confirmAns == "Y":
message = "\nSearching for %s"%(name)
print(message)
hoursWorked = int(input("Insert hours worked: "))
if hoursWorked <= 0:
print("Please insert a valid number")
elif hoursWorked > 0:
print("\nCalculete Paycheck")
hourRate = int(input("Insert the rate of each hour worked: "))
bonus = input("If a bonus was given insert it here: ")
fine = input("If a fine was given insert it here: ")
print('\n')
payment = hoursWorked*hourRate-int(fine)+int(bonus)
paymentMsg = "Your Payment is: $%d"%(payment)
print(paymentMsg)
elif confirmAns == "n" or confirmAns == "N":
print("working")
else:
print("Please answer with Y or N")
return

loop fails to terminate once conditions are met

I am trying to get my function to end the loop once it hit the return clause but it fails to do so.
Explanations rather than direct code editing would be appreciated.
def Menu():
UserMenu = True
print ("""
U.Create a Username
E.Run Exponential Calculator
Q.Exit/Quit
""")
while UserMenu not in ("U", "E", "Q"):
print("\n Error: Choice must be U, E or Q")
return UserMenu
# Function designed to retrieve first name only from fullname entry.
def get_first_name(name):
first=[""]
i = 0
while i < len(name) and name[i] !=" ":
first += name[i]
i += 1
return name[:i]
# Function designed to retrieve first initial of last name or first initial of first name if only one name input.
def get_last_initial(name):
j = len(name) - 1
while j >= 0 and name[j] !=" ":
j-=1
return name[j+1]
# Function that generates username based upon user input.
def get_username():
name = raw_input("Please enter your Full Name: ")
username = get_first_name(name) + get_last_initial(name)
return username.lower()
# Function to generate exponential numbers based upon usser input.
def print_exponential():
base = int(raw_input("Please select a base number: \n"))
power = int(raw_input("Please select a power number: \n"))
exponential = 1
while power>0:
exponential = exponential * base
print base
if power >1:
print "*",
power = power -1
return "=%d" % exponential
print Menu()
while UserMenu != "Q":
if UserMenu is "U":
UserMenu = raw_input("Please enter your Full Name: ")
print "your username is %s" % get_username()
else:
print print_exponential()
print Menu()
This is the whole program, hope it helps!
You need to update the value of UserMenu inside the loop, or else entering the loop will inherently be an infinite loop:
def Menu():
UserMenu = raw_input("""
U.Create a Username
E.Run Exponential Calculator
Q.Exit/Quit
""")
while UserMenu not in ("U", "E", "Q"):
UserMenu = raw_input("\n Error: Please input only U, E or Q:")
return UserMenu
...
all your other functions
...
user_choice = Menu()
while user_choice != "Q":
if user_choice == "U":
print "your username is %s" % get_username()
else:
print_exponential()
user_choice = Menu()
By getting new input in the loop, it will be able to meet the criteria that controls the loop. The loop you wrote will just print then check UserMenu again without changing it, so the loop will never exit.
Managed to sort out my problem using the following code.
def Menu():
result = raw_input ("""
U.Create a Username
E.Run Exponential Calculator
Q.Exit/Quit
""").upper()
while result not in ("U", "E", "Q"):
print("\n Error: Please input only U, E or Q:")
result = raw_input ("""
U.Create a Username
E.Run Exponential Calculator
Q.Exit/Quit
""").upper()
return result
# Function designed to retrieve first name only from fullname entry.
def get_first_name(full_name):
i = 0
while i < len(full_name) and full_name[i] !=" ":
i += 1
return full_name[:i]
# Function designed to retrieve first initial of last name or first initial of first name if only one name input.
def get_last_initial(full_name):
j = len(full_name) - 1
while j >= 0 and full_name[j] !=" ":
j-=1
return full_name[j+1]
# Function that generates username based upon user input.
def get_username():
username = get_first_name(full_name) + get_last_initial(full_name)
return username.lower()
# Function to generate exponential numbers based upon user input.
def print_exponential():
base = int(raw_input("Please select a base number: \n"))
power = int(raw_input("Please select a power number: \n"))
exponential = 1
while power>0:
exponential = exponential * base
print base
if power >1:
print "*",
power = power -1
return "=%d" % exponential
choice = Menu()
while choice != "Q":
if choice == "U":
full_name = raw_input("Please enter your Full Name:")
print "your username is %s" % get_username()
else:
print print_exponential()
choice = Menu()

Limiting the amount of numbers in a user input

I'm making a 4 digit password guesser in python 3. I want to make sure that you can only put in 4 digit passwords and not 5 or 6 digit passwords. Here is the code I have so far.
print('your password will not be used or saved for later use you do not have to put in your real password')
real_password = int(input("please enter your four digit phone password here:"))
computer_guess = 0000
guess_counter = 0
yes = 'yes'
no = 'no'
print ("guessing your password...")
while computer_guess < real_password:
computer_guess = computer_guess + 1
guess_counter = guess_counter + 1
print("guess number", guess_counter)
print ("your password is", computer_guess)
Before you cast the input to an int, cast it to a str instead, then you can call the len() builtin method to check the length of the entered string. Check the documentation for details on this method. If it is greater than 4, then you should recall your input call. Something like the following should work:
>>> real_password = input("please enter your four digit phone password here: ")
please enter your four digit phone password here: 1234
>>> while len(str(real_password)) != 4:
... real_password = input("please enter your four digit phone password here: ")
In this condition the loop would not be ran, however if the entered string was not equal to 4, the loop would run until that condition was satisfied.
print('your password will not be used or saved for later use you do not have to put in your real password')
def get_password():
real_password = int(input("please enter your four digit phone password here:"))
if len(str(real_password)) != 4: # condition is not met if your variable
get_password() # is not 4, easily changed if you
else: # want
return real_password
#define a method and ask it to call itself until a condition is met
#
real_password = get_password() # here the method is called and the return
computer_guess = 0 # value is saved as 'real_password'
guess_counter = 0
yes = 'yes' # these are not used in your code
no = 'no' # but I'm am sure you knew that
print ("guessing your password...")
while computer_guess != real_password: # your loop should break when the
computer_guess += 1 # is found, not some other implied
guess_counter += 1 # the '+=' operator is handy
print("guess number", guess_counter)
print ("your password is", str(computer_guess)) # explicitly define the int
# as a string
I hope that helped...

I am making a function to detect input types in Python and I can't make it work

So I am making a prime number detector as a project. I’m VERY new to programming and my friend showed me a little python. I want to make a function that detects if the user puts in a number for the input (like 5,28,156,42,63) and if the put in something else (like banana,pants,or cereal) to give them a custom error saying "Invalid Number. Please Try Again" and then looping the program until they put in a number.
Please help me make this work.
def number_checker():
user_number = int(input('Please enter a Number: '))
check = isinstance(user_number, int)
if check == True:
print ('This is a number')
if check == False:
print ('This is not a number')
1) Casting input to int would raise an exception if the input string cannot be converted to int.
user_number = int(input('Please enter a Number: '))
^^^
2) It does not make sense to cross-verify user_number with int instance as it would already be int
3) You can try
def number_checker():
while not input("enter num: ").isdigit():
print("This is not a number")
print("This is a number")
number_checker()
Try following:
def number_checker():
msg = 'Put your number > '
while True:
user_input = input(msg)
correct = user_input.isdigit()
if correct:
print("This is an integer")
return # here you can put int(user_input)
else:
print("This is not an integer")
msg = 'You typed not integer. Try again.> '
if __name__ == '__main__':
number_checker()
And it's also good rule give names for your functions as verbs according to what they do. For this one, I would give, for example def int_input or something.

Categories