【问题标题】:Unexpected multiple returns in Python 3 for single variablePython 3 中单个变量的意外多次返回
【发布时间】:2013-01-04 11:38:49
【问题描述】:

我编写了一些代码,以便人们可以输入日期。停止输入小于 1 或大于 12 的月份的错误检查应仅在其在这些范围内时返回一个值。如果我输入一些“超出范围”的数字,它会正确地重新要求重新输入一个月,但会返回所有值。怎么回事?

# the question asked to get the month input for the xml updater
def month_q():
    try:
        month = int(input('What was the month [MM] which the installers were  updated/created by xxx?:'))
    except:
        print("That was not a valid number. Please re-enter a 2 digit month")
        month_q()
    updatemonth = month_check(month)
    print("Month q returning:", updatemonth)
    return updatemonth


# check the update month is a valid month
def month_check(month):
    if month < 1:
        print("The month must be a number between 01 and 12. Please re-enter")
        month_q()
    elif month > 12:
        print("The month must be a number between 01 and 12. Please re-enter")
        month_q()
    else:
        print("Month_check returning month:", month)
        return month



# this updates the xml file with the date of the last installer    
def xml_updater():
    updatemonth = month_q()
    print("Update month:", updatemonth)


xml_updater()

结果是在输入错误月份“15”、“14”和“13”之前输入正确的“12”是:

What was the month [MM] which the installers were updated/created by xxx?:15
The month must be a number between 01 and 12. Please re-enter
What was the month [MM] which the installers were updated/created by xxx?:14
The month must be a number between 01 and 12. Please re-enter
What was the month [MM] which the installers were updated/created by xxx?:13
The month must be a number between 01 and 12. Please re-enter
What was the month [MM] which the installers were updated/created by xxx?:12
Month_check returning month: 12
Month q returning: 12
Month q returning: None
Month q returning: None
Month q returning: None
Update month: None

发生了什么事?

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    你的函数没有返回任何东西;它一次又一次地调用问题函数,但忽略了返回值:

    def month_check(month):
        if month < 1:
            print("The month must be a number between 01 and 12. Please re-enter")
            month_q()
        elif month > 12:
            print("The month must be a number between 01 and 12. Please re-enter")
            month_q()
        else:
            print("Month_check returning month:", month)
            return month
    

    如果月份小于 1 或大于 12,该函数将返回 None(默认值)。语句updatemonth = month_check(month) 然后将None 分配给updatemonth,当print("Month q returning:", updatemonth) 运行时,它会打印Month q returning: None。但是由于你递归调用了month_q,然后返回到之前的month_check() 调用,它再次返回None,以此类推。

    这是您的函数的嵌套跟踪,如 month_q 调用 month_check 调用 month_q 等:

    month_q():
        What was the month [MM] which the installers were updated/created by xxx?:15
        month_check(15):
            The month must be a number between 01 and 12. Please re-enter
            month_q():
                What was the month [MM] which the installers were updated/created by xxx?:14
                month_check(15):
                    The month must be a number between 01 and 12. Please re-enter
                    month_q():
                        What was the month [MM] which the installers were updated/created by xxx?:13
                        month_check(13):
                            The month must be a number between 01 and 12. Please re-enter
                            month_q():
                                What was the month [MM] which the installers were updated/created by xxx?:12
                                month_check(12):
                                    Month_check returning month: 12
                                    <- 12
                                Month q returning: 12
                                <- 12
                            <- None
                        Month q returning: None
                        <- None
                    <- None
                Month q returning: None
                <- None
            <- None
        Month q returning: None
        <- None
    Update month: None
    

    相反,让检查函数返回 True 或 False 以指示正确的结果,并将要求重新输入的请求留给 month_q

    使用while 循环而不是递归来做到这一点;如果你必须经常问,你最终会遇到一个递归太深的异常。

    def month_q():
        while True:
            try:
                month = int(input('What was the month [MM] which the installers were  updated/created by xxx?:'))
                if not month_check(month):
                    raise ValueError()
            except ValueError:
                print("Please re-enter a 2 digit month")
                continue
            print("Month q returning:", month)
            return month
    
    
    # check the update month is a valid month
    def month_check(month):
        if month < 1 or month > 12:
            print("The month must be a number between 01 and 12")
            return False
        return True
    

    您也可以内联该检查:

    def month_q():
        while True:
            try:
                month = int(input('What was the month [MM] which the installers were  updated/created by xxx?:'))
                if month < 1 or month > 12:
                    raise ValueError()
            except ValueError:
                print("Please re-enter a 2 digit month between 01 and 12.")
                continue
            print("Month q returning:", month)
            return month
    

    使用毯子except: 子句绝不是一个好主意;在上面的代码中,当您输入一个非整数值时,我捕获了int() 引发的ValueError,如果您输入了一个整数但它不是介于1 和 12 包括在内。这大大简化了“不是一个月”的错误处理。

    【讨论】:

    • 感谢 Martijn。这是一个很好的解决方案。我很欣赏这个问题一定是'print'指的是previoulsy返回的'none'值,但不知道它如何或为什么可以将它们存储在某个地方。我错误地认为最终的正确值会相应地覆盖月份的值。
    【解决方案2】:

    试试这个:

    try:
        month = int(input('What was the month [MM] which the installers were  updated/created by xxx?:'))
    except:
        print("That was not a valid number. Please re-enter a 2 digit month")
        month_q()
        break
    

    这应该会中断不正确月份的打印

    另外,你应该改变

    updatemonth = month_check(month)
    print("Month q returning:", updatemonth)
    return updatemonth
    

    到:

    updatemonth = month_check(month)
    try:
        updatemonth
    except NameError:
        updatemonth = None
    
    if updatemonth is None:
        break
    print("Month q returning:", updatemonth)
    return updatemonth
    

    【讨论】:

    • 感谢 Wampie 的回答。
    猜你喜欢
    • 1970-01-01
    • 2014-05-14
    • 2021-10-19
    • 1970-01-01
    • 2020-03-29
    • 2017-07-02
    • 2016-02-02
    • 1970-01-01
    相关资源
    最近更新 更多