我对函数prompt_int的定义有什么问题?

时间:2015-07-25 12:50:27

标签: python random

我一直在尝试编写一个数学测验,它既有效又有效。查看我的代码,我看到我有很多整数输入,这导致我有程序提出问题/退出系统,如果标准没有得到满足,那么为了帮助我,我认为这将是有用的创建一个新功能。这是我的尝试:

def prompt_int(prompt=''):
    while True:
        if status == prompt_int(prompt=''):
            val = input(prompt)
            if val in (1,2):
                return int(val)
                return true
        elif status != prompt_int(prompt=''):
            val = input(prompt)
            if val in (1,2,3):
                return int(val)
                return true
        else:
            print("Not a valid number, please try again")

然而,当我尝试围绕我的代码实现这个功能时,它没有正常工作,因为它说状态没有定义,但是当我确定状态时它会进入递归循环。我该如何解决这个问题?

在尝试实现此功能之前,这是我的原始代码:

import sys
import random
def get_bool_input(prompt=''):
    while True:
        val = input(prompt).lower()
        if val == 'yes':
            return True
        elif val == 'no':
            return False
        else:
            sys.exit("Not a valid input (yes/no is expected) please try again")
status = input("Are you a teacher or student? Press 1 if you are a student or 2 if you are a teacher")# Im tring to apply the new function here and other places that require integer inputs
if status == "1":
    score=0
    name=input("What is your name?")
    print ("Alright",name,"welcome to your maths quiz."
            "Remember to round all answer to 5 decimal places.")
    level_of_difficulty = int(input(("What level of difficulty are you working at?\n"
                                 "Press 1 for low, 2 for intermediate "
                                    "or 3 for high\n")))
    if level_of_difficulty not in (1,2,3):
        sys.exit("That is not a valid level of difficulty, please try again")
    if level_of_difficulty == 3:
        ops = ['+', '-', '*', '/']
    else:
        ops = ['+', '-', '*']
    for question_num in range(1, 11):
        if level_of_difficulty == 1:
            number_1 = random.randrange(1, 10)
            number_2 = random.randrange(1, 10)
        else:
            number_1 = random.randrange(1, 20)
            number_2 = random.randrange(1, 20)
        operation = random.choice(ops)
        maths = round(eval(str(number_1) + operation + str(number_2)),5)
        print('\nQuestion number: {}'.format(question_num))
        print ("The question is",number_1,operation,number_2)
        answer = float(input("What is your answer: "))
        if answer == maths:
            print("Correct")
            score = score + 1
        else:
            print ("Incorrect. The actual answer is",maths)
    if score >5:
        print("Well done you scored",score,"out of 10")
    else:
        print("Unfortunately you only scored",score,"out of 10. Better luck next time")
    class_number = input("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
    while class_number not in ("1","2","3"):
        print("That is not a valid class, unfortunately your score cannot be saved, please try again")
        class_number = input("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
    else:
        filename = (class_number + "txt")
        with open(filename, 'a') as f:
            f.write("\n" + str(name) + " scored " + str(score) +  " on difficulty level " + str(level_of_difficulty))
        with open(filename, 'a') as f:
            f = open(filename, "r")
            lines = [line for line in f if line.strip()]
            f.close()
            lines.sort()
        if get_bool_input("Do you wish to view previous results for your class"):
            for line in lines:
                print (line)
        else:
            sys.exit("Thanks for taking part in the quiz, your teacher should discuss your score with you later")
if status == "2":
    class_number = input("Which classes scores would you like to see? Press 1 for class 1, 2 for class 2 or 3 for class 3")
    if class_number not in (1,2,3):
        sys.exit("That is not a valid class")
    filename = (class_number + "txt")
    with open(filename, 'a') as f:
        f = open(filename, "r")
        lines = [line for line in f if line.strip()]
        f.close()
        lines.sort()
        for line in lines:
            print (line)

3 个答案:

答案 0 :(得分:0)

嗯,只是一部分:

def prompt_int(prompt=""):
    while True:
        val = input(prompt)
        if val in ("1", "2"):
            return int(val), True

会一次又一次地问。并在用户输入" 1"或" 2"!
但更好的是:"如果是" 12":

答案 1 :(得分:0)

def prompt_int(prompt=""):
    while True:
        val = input(prompt)
        if val.isdigit():
            return int(val)

如果您不想将有效值发送给您,您可以将代码更改为上述函数。

但您也可以将其更改为系统退出:

def prompt_int(prompt="", authorized=()):
    while True:
        val = raw_input(prompt)
        if val.isdigit():
            if int(val) in authorized:
                return int(val)
            else:
                sys.exit("Bla bla bla too bad")

答案 2 :(得分:0)

def prompt_int(prompt=''):
    while True:
        if status == prompt_int(prompt=''):

此行将查找名称" status"在全局命名空间(模块的命名空间)中,如果没有名为' status'的全局变量,则引发NameError。 如果有一个,它将递归地调用prompt_int而没有任何可能的终止,理论上在无限递归中产生,但实际上(至少在CPython中)RuntimeError当它会到达最大递归深度。

还有很多其他事情不会像你期望的那样发挥作用:

        val = input(prompt)
        if val in (1,2):

在Python 3.x中,val将是一个字符串,因此它永远不会与int相等。在Python 2.x中,input()eval(raw_input())的快捷方式,它可能会返回int,但由于它无条件地执行不受信任的代码,因此也是一个巨大的安全漏洞。

            return int(val)
            return true

显然,第二个return语句将永远不会执行,因为该函数将在第一个语句中退出。

更简单的实现可能如下所示:

# rebinds raw_input to input for python < 3
import sys
if sys.version_info.major < 3:
    input = raw_input

def prompt_int(prompt='', choices=None):
    while True:
        val = input(prompt)

        try:
            val = int(val)
            if choices and val not in choices:
                raise ValueError("{} is not in {}".format(val, choices))
            return val
        except (TypeError, ValueError) as e:
                print(
                    "Not a valid number ({}), please try again".format(e)
                    )

虽然我们正在努力,但代码的其他部分还有改进的余地。让我们从这开始:

def get_bool_input(prompt=''):
    while True:
        val = input(prompt).lower()
        if val == 'yes':
            return True
        elif val == 'no':
            return False
        else:
            sys.exit("Not a valid input (yes/no is expected) please try again")

第一点:你的命名不一致。如果您的其他函数名为prompt_int,则此函数应命名为prompt_bool。此外,您有一个函数(prompt_int)永远循环,另一个函数退出整个程序无效输入,这是另一个不一致。如果要允许用户在任何提示符处退出,请为其提供显式选项,即:

def prompt_bool(prompt, quit='Q'):
    prompt += " (hit '{}' to exit) : ".format(quit)
    while True:
        val = input(prompt).strip().upper()
        if val == quit:
            sys.exit("Goodbye")
        elif val == 'yes':
          return True
        elif val == 'no':
          return False
        else:
            print "Invalid input '{}', please try again".format(val)

当然,您希望在prompt_int()中提供相同的选项,这会产生更通用的功能:

def get_input_or_quit(prompt, quit="Q"):
    prompt += " (hit '{}' to exit) : ".format(quit)
    val = input(prompt).strip()
    if val.upper() == quit:
        sys.exit("Goodbye")
    return val

def prompt_bool(prompt):
    while True:
        val = get_input_or_quit(prompt).lower()
        if val == 'yes':
          return True
        elif val == 'no':
          return False
        else:
            print "Invalid input '{}', please try again".format(val)

当然,您也可以通过调用input中的get_input_or_quit来取代对prompt_int的通话。

我们可以继续 - 将所有代码拆分为独立的,自包含的函数,编写&#34; main()&#34;驱动它们的功能(而不是让主要的&#34;部分位于顶层),显然使用operator模块而不是eval()