为用户输入递归调用函数

时间:2015-05-11 05:38:16

标签: python function python-2.7 recursion input

我试图制作一个石头剪刀游戏, 并且我正在尝试验证输入。

def player1():
    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!"
        player1() #I know I can run a While loop, but I need to run it this way.

print(player1())

如果我在第一次尝试时输入正确的输入,一切正常。 但是如果我在第一次尝试时输入错误的输入,并在第二次输入正确的输入,我在输出中得到None,而不是RPS选项的第一个字母。

我错过了什么?

4 个答案:

答案 0 :(得分:4)

你想要循环输入。你当前正在做的是递归调用player1,并且递归的情况没有显式的返回值(因此返回None)。

这样做很简单:输入无效时,再次提示。我正在使用这种修改版本的“while True break”风格;它实现了同样的目标。我们无限循环,如果我们想要的条件有效,我们返回;否则,我们会提示输入并再次循环。

def player1():
    while True:
        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!"

作为if语句的替代方法,有一种更简洁的方法可以通过in运算符表达它。

if x in ('r', 'p', 's', 'rock', 'paper', 'scissors'):

作为原始问题的补充(因为它表示你必须递归地执行),我必须强烈提醒你不要通过递归来进行任何输入评估。 Python的调用堆栈大小约为1,000,这意味着在程序无法恢复崩溃之前,你有一个非常有限(但相当大)的尝试次数。

不仅如此,而且您的操作堆栈将不必要地填充方法调用,其行为方式与循环类似。为了记忆,除了绝对递归上限之外,不使用递归。

如果你绝对必须,我强烈建议 反对 这样做,那么你只需要从你的迭代案例中返回。< / p>

def player1():
    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())

答案 1 :(得分:4)

@ Makoto的一个改进版本的例子:

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

这比许多or表达式更简洁 ,如果你想要检查很多条件,它会有点笨拙!

一点解释:

  

我们正在检查x我们的用户输入)是否在预定义的有效输入列表中。

更加通用的版本可重复使用

示例:可重用,非递归:

#!/usr/bin/env python


from __future__ import print_function  # For Python 2/3 compat


try:
    input = raw_input  # For Python 2/3 compat
except NameError:
    pass


def prompt(prompt="Enter: ", valid=None):
    s = input(prompt)
    while valid and s not in 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"])

<强>演示:

$ 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 :抱歉,我没有使用递归来回答您的问题。 IHMO这不是递归的好用例。 哦好 :)但是;这很容易改变:

示例:可重用,递归

def userprompt(prompt="Enter: ", valid=None):
    s = input(prompt)
    while valid and s not in valid:
        print("Invalid input! Please try again. Valid inputs are {0:s}".format(" ".join(valid)))
        s = userprompt(prompt, valid)
    return s

答案 2 :(得分:1)

else分支中,您的函数(特别是对函数的第一次调用)不会return。在没有return的任何事情的Python函数中,总是隐式地返回None

答案 3 :(得分:0)

我正在为完整性添加此答案,因为您要求递归解决方案。这是我最接近你的解决方案:

def player1():
    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()

正如你所看到的,你所遗忘的只是一个回报声明。更可读的方式可能是:

def player1():
    playerInput=None
    while playerInput not in ('r', 'p', 's', 'rock', 'paper', 'scissors'):
        if playerInput is not None:
            print("Error - wrong input!")
        playerInput = raw_input("please select: Rock(r)/Paper(p)/Scissors(s)").lower()
    return playerInput[0]

使用do while循环会更干净,但python缺少该构造。