Calling A Function Recursively For User Input
Solution 1:
You're going to want to loop on input. What you're doing currently is recursively calling player1
, and the recursive case doesn't have an explicit return value (hence, None
is returned).
The way you do this is simple: while there is invalid input, prompt again. I'm using a modified version of this in the vein of the "while True break" style; it accomplishes the same goal. We loop indefinitely, and if the condition we want is valid, we return; otherwise, we prompt for input and loop again.
def player1():
while True:
x = raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ").lower()
ifx== 'r'orx== 'p'orx== 's'orx== 'rock'orx== 'paper'orx== 'scissors':
return x[0]
else:
print "Error - wrong input!"
As an alternative to that if
statement, there is a slightly more clean way to express it via the in
operator.
if x in('r', 'p', 's', 'rock', 'paper', 'scissors'):
As an addendum to your original question (as it says that you have to do it recursively), I must strongly caution you against doing any input evaluation through recursion. Python has a call stack size of around 1,000, which means that you have a very finite (yet reasonably large) amount of tries before the program irrecoverably crashes.
Not just that, but your operation stack will be unnecessarily filled with method calls that behave in a similar fashion to a loop. For memory's sake in addition to the absolute recursion ceiling, do not use recursion for this.
If you absolutely must, and again I strongly advise against doing this, then you simply have to return from your iterative case.
defplayer1():
x = (raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ")).lower()
if x == 'r'or x == 'p'or x == 's'or x == 'rock'or x == 'paper'or x == 'scissors':
return x[0]
else:
print"Error - wrong input!"return player1() #I know I can run a While loop, but I need to run it this way.print(player1())
Solution 2:
An improved version of @Makoto's example:
def player1():
x = raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ").lower()
while True:
if x in ['r', 'p', 's', 'rock', 'paper', 'scissors']:
return x[0]
else:
print"Error - wrong input!"
x = raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ").lower()
This is a little more concise than many or
expressions which gets a bit unwieldy if you have a lot of conditions you want to check!
A little explanation:
We're checking to see
x
(our user input) is in pre-defined list of valid inputs.
An even more generalized version of this which becomes reusable:
Example: (reusable, non-recursion:)
#!/usr/bin/env pythonfrom __future__ import print_function # For Python 2/3 compattry:
input = raw_input # For Python 2/3 compatexcept NameError:
passdefprompt(prompt="Enter: ", valid=None):
s = input(prompt)
while valid and s notin valid:
print("Invalid input! Please try again. Valid inputs are {0:s}".format(" ".join(valid)))
s = input(prompt)
return s
x = prompt("Enter action ([r]ock, [p]aper, [s]cissors): ", ["r", "p", "s", "rock", "paper", "scissors"])
Demo:
$ python foo.py
Enter action([r]ock, [p]aper, [s]cissors): a
Invalid input! Please try again. Valid inputs are r p s rock paper scissors
Enter action([r]ock, [p]aper, [s]cissors): foo
Invalid input! Please try again. Valid inputs are r p s rock paper scissors
Enter action([r]ock, [p]aper, [s]cissors): r
$ python foo.py
Enter action([r]ock, [p]aper, [s]cissors): a
Invalid input! Please try again. Valid inputs are r p s rock paper scissors
Enter action([r]ock, [p]aper, [s]cissors): foo
Invalid input! Please try again. Valid inputs are r p s rock paper scissors
Enter action([r]ock, [p]aper, [s]cissors): rock
PS: Sorry I didn't answer your question using recursion. IHMO this is not a good use-case for recursion. Oh well :) However; this is pretty easy to change:
Example: (reusable, recursive)
defuserprompt(prompt="Enter: ", valid=None):
s = input(prompt)
while valid and s notin valid:
print("Invalid input! Please try again. Valid inputs are {0:s}".format(" ".join(valid)))
s = userprompt(prompt, valid)
return s
Solution 3:
In the else
branch your function (the first call to your function, in particular) doesn’t return
anything. In Python functions that do not return
anything always return None
implicitly.
Solution 4:
I'm adding this answer for completeness sake, as you do ask for a recursive solution. Here is my solution that is closest to yours:
def player1():
x = (raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ")).lower()
ifx== 'r'orx== 'p'orx== 's'orx== 'rock'orx== 'paper'orx== 'scissors':
return x[0]
else:
print "Error - wrong input!"return player1()
As you can see, all you've forgotten is a return statement. A more readable way might be:
defplayer1():
playerInput=Nonewhile playerInput notin ('r', 'p', 's', 'rock', 'paper', 'scissors'):
if playerInput isnotNone:
print("Error - wrong input!")
playerInput = raw_input("please select: Rock(r)/Paper(p)/Scissors(s)").lower()
return playerInput[0]
It would be even cleaner with a do while loop, but python lacks that construct.
Post a Comment for "Calling A Function Recursively For User Input"