0

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!

1
  • You have to return your changed value back to the caller. Commented Jul 4, 2020 at 3:14

4 Answers 4

1

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()
Sign up to request clarification or add additional context in comments.

Comments

1

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()

Comments

1

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.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.