6

I am a python noob and was hoping someone could point me in the right direction here.

I am trying to get user input and only accepting upper and lower case letters.

If anything else is entered then I want to ask the user again for valid input (a letter).

My code works (to a degree) - if the correct value is entered it works as expected, but if invalid values are entered it asks the question again but now even if valid values are entered it requires the value entered in as many times as there were wrong answers.

I understand there may be better ways to do what I want (and I have a different working solution below but my curiosity is why this script behaves as it does)

import string

def get_guess():
    lower_letters = list(string.ascii_lowercase)
    while True:
        try:
            guess = input('Guess a letter: ')
            if guess.lower() in lower_letters:
                return guess
            else:
                get_guess()
        except:
            print("That's not a valid option!")

letter = get_guess()
print(letter)

To help explain here is the code in action: Gif of Code running

I know I can replace that code with the code below and get the result I am after but can you explain why the top code is doing what it is - once again if this is an obvious noob question I just couldn't let it go.

Working code:

import re
while 1:
    inputString = input()
    if re.match(r"^[A-Z,a-z]$", inputString):
        print("Input accepted")
        break
    else:
        print("Bad input, please try again")

Please also feel free to point me to any other resource if there is a better way to get the same result rather than the 2 snippets I have provided - I am always willing to learn.

Thank you all in advance.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
Rob
  • 95
  • 5
  • 1
    That's because this is a recursive function. You can visualize this code by using pythontutor. – Ch3steR Mar 17 '20 at 11:02
  • 3
    I wish more people took the time to construct questions like this. Thank you for your efforts, OP. – Paritosh Singh Mar 17 '20 at 11:04
  • 2
    I think you are confused with if else and try except concepts. When do you think your script will raise an exception? – Eternal Mar 17 '20 at 11:06
  • 3
    The issue is you're not returning the recursive call, you just have `else: get_guess()` while you need `else: return get_guess()`. Otherwise the `while` loop of the outer function still runs. – a_guest Mar 17 '20 at 11:07
  • @Rakesh https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response is certainly a great resource regarding the best ways to get user input. But it doesn't explain why Rob's recursive code behave like it does when given bad input, and that's his main reason for posting this question; he already figured out a better way to get input. – PM 2Ring Mar 17 '20 at 11:21
  • BTW Rob, as Kevin explains in the linked answer, you should avoid recursion when getting user input, so `get_guess` should *not* call `get_guess`. – PM 2Ring Mar 17 '20 at 11:24
  • A better title might be 'Recursion giving unexpected results'. In any case, recursion and iteration are two ways to do 'repetition with variation'. Using both to do the same thing does not work well ;-). In this case iteration is more appropriate. – Terry Jan Reedy Mar 21 '20 at 17:30

0 Answers0