(Python) Try and Except within a User-Defined Function - python

I have worked on many projects (school projects, I'm not too advanced), and have found that in many programs where I require the user to input a value that is an integer, or decimal(float), I need to use a "try-except" statement, within a while loop, in order to make certain that the user inputs the required value type.
For example:
def main():
userValue = input("Please enter an integer: ")
while(True):
try:
userValue = int(userValue)
break
except:
userValue = input("That is not an integer, try again: ")
print("The integer you entered is: " + str(userValue))
main()
# Input: SADASD (A non-integer value)
# Output: "That is not an integer, try again: "
# Second-Input: 3
# Second-Output: "The integer you entered is: 3"
Understandably, typing out this entire section of code repeatedly, in a program that requires user input multiple times, is not really efficient. So understanding, that user-defined functions help when I need to perform one action, multiple times. With this in mind, I defined my own function with that same try-except statement in a while loop. However, now, when I use the function, instead of printing the same output previously, rather, it prints out the first value the user had input.
For example:
def valueCheck_Integer(userInput):
while(True):
try:
userInput= int(userInput)
break
except:
userInput = input("That is not an integer, try again: ")
def main():
userValue = input("Please enter an integer: ")
valueCheck_Integer(userValue)
print("The integer you entered is: " + str(userValue))
main()
# Input: SADASD (A non-integer value)
# Output: "That is not an integer, try again: "
# Second-Input: SASASD
# Second-Output: "That is not an integer, try again: "
# Third-Input: 3
# Third-Output: SADASD (The first value that the user Input, instead of 3)
Can someone please explain to me why this happens, and some suggestions on how to fix it?
Thank you!

It's probably going to be easier to expect the function to get/check/return the integer rather than check input you already have. You can pass it the string to use for asking for the value (you could also pass the error string). It will keep asking until it's successful and then return the number you want:
def get_integer(question):
while(True):
try:
return int(input(question))
except ValueError:
question = "That is not an integer, try again:"
def main():
userValue = get_integer("Please enter an integer: ")
print("The integer you entered is: " + str(userValue))
main()

It is because of you are printing userValue instead of userInput.
I used return make it easier. So the code will be like this
def valueCheck_Integer(userInput):
while(True):
try:
userInput= int(userInput)
break
except:
userInput = input("That is not an integer, try again: ")
return userInput
def main():
userValue = input("Please enter an integer: ")
print("The integer you entered is: " + str(valueCheck_Integer(userValue)))
main()
You can make your code smaller like this:
def valueCheck_Integer(userInput):
while not(userInput.isdigit()):
userInput = input("That is not an integer, try again: ")
return userInput
def main():
userValue = input("Please enter an integer: ")
print("The integer you entered is: " + str(valueCheck_Integer(userValue)))
main()

First off, Good Question.
To understand what is going on, we first have to talk about scope of a variable.
When you define a variable outside a function, it becomes something called a global variable. This basically means that you can access it from anywhere in your code. When you define the variable within a function, it becomes a local variable. This means that it is only accessible from within your function. Finally, when a function gets passed in a variable, it gets its own local copy of the variable to work with.
Now let's look at your code.
when you call valueCheck_Integer(userInput): the function gets its own copy of userInput to work with. thus all the changes that the function does modifies the local userInput while the global userInput stays the same. As such, when the user enters a correct answer, the global userInput is the one that gets printed and the changes the function makes to local userInput is lost.
So, how can we fix this?
There are two main methods:
1)Using the global keyword
def valueCheck_Integer(userInput):
global userInput
while(True):
try:
userInput= int(userInput)
break
except:
userInput = input("That is not an integer, try again: ")
This keyword asks the function to modify the global userInput
2)Returning a value
def valueCheck_Integer(userInput):
while(True):
try:
userInput= int(userInput)
break
except:
userInput = input("That is not an integer, try again: ")
return userInput
def main():
userValue = input("Please enter an integer: ")
print("The integer you entered is: " + str(valueCheck_Integer(userValue)))
main()
This works by returning the local copy of userInput and modifying global userInput to equal local userInput
The second code I used was from
Osadhi Virochana Jayasinghe Si's answer.

It's because, if you see your line of code where you print the final output -:
print("The integer you entered is: " + str(userValue))
you will realise that the value you are printing is the one you take the first time from the input function. But this is not the value you have been working on to achieve in your other function.
So for you to rather get that value, the function in some way has to return it back to you.
For this you should allow the function to return the value in the last line.
like so -:
return userInput
and then change the line where you call function so it saves the value returned.
like so -:
userValue = valueCheck_Integer(userValue)
Also as mentioned by others using the global keyword you can define the variable in global scope.
But this is really not a good practice until really needed as it can increase the amount of space that the var is taking, before the variable only took the space for a limited time for when the function is called, but now the variable takes space throughout the time the program runs.
While return will not do so as it will only return the value and once assigned to the already defined variable it will remove the returned value from space.
This should hopefully fix your problem.
I hope this helps.
And also hope that you're safe during the time of this ongoing pandemic.

Related

How to automatically fill in a module input using a list

I have a basic python module that I want to run repeatedly using a list but the variable is declared as an input and is not able to be pre-defined in the module.
def testing(): var = input("Please enter something: ") print("You entered: " + var)
If I run through the module in a loop with different strings:
for i in ['lol','lel','lal']: testing() print(i)
the different strings will not be used as input and instead be printed after. Is there any way to have those strings become the input for the module?
Not sure exactly what you try to achieve and why you can't change the input if you don't necessarily need it. You could try doing something like this and send an empty string when you actually need an input?
def testing(input):
if input == "":
var = input("Please enter something: ")
print("You entered: " + var)
else:
print("You entered: " + input)
for i in ['lol','lel','lal']:
testing()
print(i)

Trying to validate a text input, so it allows characters in the alphabet only as the input but I'm having problems. (Python)

So, I have a homework where I'm assigned to write multiple python codes to accomplish certain tasks.
one of them is: Prompt user to input a text and an integer value. Repeat the string n
times and assign the result to a variable.
It's also mentioned that the code should be written in a way to avoid any errors (inputting integer when asked for text...)
Keep in mind this is the first time in my life I've attempted to write any code (I've looked up instructions for guidance)
import string
allowed_chars = string.ascii_letters + "'" + "-" + " "
allowed_chars.isalpha()
x = int
y = str
z = x and y
while True:
try:
x = int(input("Enter an integer: "))
except ValueError:
print("Please enter a valid integer: ")
continue
else:
break
while True:
try:
answer = str
y = answer(input("Enter a text: "))
except ValueError:
print("Please enter a valid text")
continue
else:
print(x*y)
break
This is what I got, validating the integer is working, but I can't validate the input for the text, it completes the operation for whatever input. I tried using the ".isalpha()" but it always results in "str is not callable"
I'm also a bit confused on the assigning the result to a variable part.
Any help would be greatly appreciated.
Looks like you are on the right track, but you have a lot of extra confusing items. I believe your real question is: how do I enforce alpha character string inputs?
In that case input() in python always returns a string.
So in your first case if you put in a valid integer say number 1, it actually returns "1". But then you try to convert it to an integer and if it fails the conversion you ask the user to try again.
In the second case, you have a lot of extra stuff. You only need to get the returned user input string y and check if is has only alpha characters in it. See below.
while True:
x = input("Enter an integer: ")
try:
x = int(x)
except ValueError:
print("Please enter a valid integer: ")
continue
break
while True:
y = input("Enter a text: ")
if not y.isalpha():
print("Please enter a valid text")
continue
else:
print(x*y)
break

How to Make a Dictionary Accept any Integer to Trigger a Function

Let's say you have the following code:
def statementz():
print("You typed in", number)
digits = {
56 : statementz
}
while True:
try:
number = int(input("Enter a number: "))
except TypeError:
print("Invalid. Try again.\n")
continue
else:
digits.get(number, lambda : None)()
break
I am wondering if there is a way so that one could allow the dictionary to trigger the "statementz" function if the variable "number" holds the value of any integer/float, and not just the integer that is given in the (rather sloppy) example above.
Is it possible to do this? Thank you in advance for any guidance given!
If you want any number to be passed to statementz(), you can simply call it directly after validating it as a number. A dict is only useful if you want to map different numbers to different functions, which is not the behavior you are asking for. Also note that your statementz() should take a number as a parameter since you want to print the number in the function:
def statementz(number):
print("You typed in", number)
while True:
try:
number = float(input("Enter a number: "))
statementz(number)
except TypeError:
print("Invalid. Try again.\n")
Without try-except:
Try using:
def statementz(number):
print("You typed in", number)
while True:
number = input("Enter a number: ")
if number.isdigit():
statementz(number)
break
else:
print("Invalid. Try again.\n")
Example Output:
Enter a number: Apple
Invalid. Try again.
Enter a number: 12ab
Invalid. Try again.
Enter a number: --41-
Invalid. Try again.
Enter a number: 24
You typed in 24

Convert raw_input’s output to integer

def total():
n = prompt()
answer = (n-2)*180
print ("The polygon has", answer, "sides.")
def prompt():
x = raw_input("Type number: ")
return x
I'm trying to get n which is equal to the output of prompt to be an integer so that math can be done on it. How would I do this?
raw_input returns a string, so you cannot use it for any calculations. If you want to have an integer instead, you can use the int function to convert the value. You can do that either within your prompt function, or later in the calling function (although it would make more sense to have a function that asks the user for a number return one):
def prompt ():
x = raw_input("Type a number: ")
return int(x)
Note, that int() may raise a ValueError for any user entered value that is not a valid integer. In that case, you should catch the exception and prompt the user again to correct the input. See this question on how that would work.

Python not returning expected value

I simply cannot understand what is happening here. The problem is important for my homework (studying programming so I'm a beginner... also my English is not that good, sorry).
I am trying to read a string... it can be either a number or a set number of commands.
I'll just give a very small example of what I'm trying to do and what is going wrong.
def validate():
choice = str(input(">>> "))
if (choice == "exit"):
return 0 # should exit validate
else:
try:
aux = int(choice) # Tries converting to integer
except:
print("Insert integer or exit")
validate() # If it can't convert, prompts me to try again through
# recursivity
else:
return aux
rezult = validate()
print (rezult)
Problem is that this small script returns totally random stuff.
If "exit", returns "None".
If first input is correct, it returns correct number.
If first input is an "error" and second input is correct, it's "None" again and I simply can't understand what is going wrong... Why it doesn't want to work or what should I do (alternatively).
In case you enter the except block, the function validate() uses a recursive call to call itself. When this call returns, it returns to the place where the function was called, i.e. into the except block. The return value of validate() is ignored at this point, and control reaches the end of the outer call without hitting a return statement, so None is implicitly returned.
Don't use recursion here. Use a loop.
Use raw_input instead of input (unless you are on Python 3.x):
choice = raw_input(">>> ")
And you are missing a return here:
except:
print ("Insert integer or exit")
return validate () # <<< here
Also, don't use recursion for this. Use a loop instead.
Ok, decided to listen and changed the recursive part into a loop, thank you for your help. (Works now)
def validateChoice():
condition = False
while (condition == False):
choice = str (input (">>> "))
if (choice == "exit"):
return 0
else:
try:
aux = int (choice)
except:
print ("Insert integer or 'exit'")
else:
condition = True
return aux

Categories

Resources