【问题标题】:Python - UnboundLocalError: local variable referenced before assignment in a loopPython - UnboundLocalError:在循环中赋值之前引用的局部变量
【发布时间】:2018-02-20 06:46:36
【问题描述】:

我是 Python 的新手,我正在尝试从 Zed Shaw 的书中做一个练习。我试图为我的问题找到答案并自行调试代码,但没有成功。

我收到“分配前引用的局部变量”错误,但仅在之后 循环其中一个分支。例如。当我在输入中选择非整数字符 (chosen_car = int(input("> "))) 时,该函数应该从头开始并允许我选择正确的值。但是当我之后选择正确的数字时,我得到一个错误。在 shell 中它看起来像这样:

You're about to start a race.
You should buy a car before you start.
Let's see how much you have in your pocket.
> Check your poocket (hit enter to proceed)
Oh, you have 1 thousands. Let's see what you can buy with it
> Ok
Choose your car:
    1. Race Car 4k
    2. Sedan 2k
    3. Pickup 1k
> w
Don't waste my time, choose a correct number.
Choose your car:
    1. Race Car 4k
    2. Sedan 2k
    3. Pickup 1k
> 3
Congratulations, you bought a Pickup
Traceback (most recent call last):
  File "ex36.py", line 35, in <module>
    choose_a_car()
  File "ex36.py", line 17, in choose_a_car
    if chosen_car >= 0 and chosen_car <= 3:
UnboundLocalError: local variable 'chosen_car' referenced before assignment

这是代码。我会很乐意为您提供帮助。

from random import randint
from sys import exit

def choose_a_car():

    # the list of cars [cost, name]
    cars = [[4, "Hidden Super Car"], [4, "Race Car"], [2, "Sedan"], [1, 
    "Pickup"]]

    print(f"Choose your car:\n\t1. {cars[1][1]} {cars[1][0]}k \n\t2. 
    {cars[2][1]} {cars[2][0]}k \n\t3. {cars[3][1]} {cars[3][0]}k")

    try:
        chosen_car = int(input("> "))
    except ValueError:
        print("Don't waste my time, choose a correct number.")
        choose_a_car()

    if chosen_car >= 0 and chosen_car <= 3:
        if cars[chosen_car][0] <= money:
            print(f"Congratulations, you bought a {cars[chosen_car][1]}")
        else:
            print("Unfortunately, you don't have enough money to buy this 
            car")
            choose_a_car()
    else:
        print("There is no such a car")
        choose_a_car()


print("You're about to start a race.")
print("You should buy a car before you start.")
print("Let's see how much you have in your pocket.")
input("> Check your poocket (hit enter to proceed)")
money = int(randint(1,4))
print(f"Oh, you have {money} thousands. Let's see what you can buy with it")
input("> Ok")
choose_a_car()

print("Let's start a race!")
print("1! \n2! \n3! \nSTART!")

【问题讨论】:

  • 在像您这样的问题中,清楚地了解程序结构很重要。请格式化您的代码。我们需要知道哪些语句在函数中,哪些不在。
  • 所以常客不推荐 Zed 的书。请参阅here 以获得更好的介绍列表。
  • 不要在 Python 中循环使用的地方使用递归。
  • 感谢您的提示,我已对代码进行了格式化以使其更清晰。书单也很有用,我一定会用到的。

标签: python python-3.x


【解决方案1】:
try:
    chosen_car = int(input("> "))
except ValueError:
    print("Don't waste my time, choose a correct number.")
    choose_a_car()

此代码 sn-p 使用递归。因此,如果用户输入了无效的输入,程序将进入except 块并再次调用该函数。如果用户在第二次调用中输入了正确的号码,第二次调用将成功终止,您将返回到第一次函数调用。但是,在第一次调用中,chosen_car 未定义,因为输入无效。因此程序因错误而崩溃。您可以尝试使用如下标志来代替递归:

myFlag = True
while( myFlag):
    try:
        chosen_car = int(input("> "))
        myFlag = False
    except ValueError:
        print("Don't waste my time, choose a correct number.")

通过这样做,如果程序在chosen_car = int(input("&gt; ")) 行崩溃,myFlag 不会设置为False,程序会继续从用户那里获取输入。

我还没有检查代码,但我想应该可以。

【讨论】:

  • 它成功了 - 非常感谢。它还有助于更好地理解问题。我认为在输入无效输入后,第二次调用中的函数从一开始就开始了,python 不会“记住”第一次调用。从你所说的我理解,事实上它是相反的 - 输入正确的值后,程序开始再次进行第一次调用。
【解决方案2】:

通过在 try 语句之前将 selected_car 设置为 None 来初始化它。您得到了异常,因为当您到达第 17 行时,该变量尚未初始化。

【讨论】:

  • 现在会引发 TypeError
  • 它对我不起作用。现在我在第 19 行收到一个新错误:TypeError: '>=' not supported between 'NoneType' 和 'int' 的实例。我不知道为什么会这样。当程序到达这一行时,新值被分配给 selected_car 变量,然后将其转换为整数。
  • 未分配新值。阅读范围。
【解决方案3】:

这是你的问题:

try:
    chosen_car = int(input("> "))
except ValueError:
    print("Don't waste my time, choose a correct number.")
    choose_a_car()

if chosen_car >= 0 and chosen_car <= 3:

如果这进入了例外,那么选择的汽车将不会被定义。我建议您在 try 之外定义它,或者将整个内容放在 while 循环中,而不是使用 choose_a_car() 递归。

【讨论】:

  • 第一个解决方案对我不起作用。我在第 19 行遇到了一个新错误:TypeError: '>=' not supported between 'NoneType' 和 'int' 的实例。我不确定为什么会得到它,因为当程序到达第 19 行时,应该将新值分配给 selected_car 变量。
  • 是的,第一个解决方案行不通。只有第二种解决方案(由您接受的答案实施)
  • 没错。我不确定我是否理解为什么第一个不起作用。是不是因为Python在得到正确的值后再次重复第一次调用并且它记住了原始输入?
  • 它不记得原始输入,因为它进入了例外。使用第二种解决方案,选择的汽车将是您在尝试之外定义的任何值,在这种情况下,它不是。由于无法将None0 进行比较,因此会引发错误
【解决方案4】:

你可以这样做:

from random import randint


def get_number(msg, minimum, maximum):
    while True:
        try:
            num = int(input(msg))
        except ValueError:
            print("Don't waste my time, choose a correct number.")
        else:
            if num >= minimum and num <= maximum:
                return num


def choose_a_car():

    # the list of cars [cost, name]
    cars = [[4, "Hidden Super Car"], [4, "Race Car"], [2, "Sedan"], [1, "Pickup"]]

    print(f"Choose your car:\n\t1. {cars[1][1]} {cars[1][0]}k \n\t2. {cars[2][1]} {cars[2][0]}k \n\t3. {cars[3][1]} {cars[3][0]}k")

    chosen_car = get_number('> ', minimum=1, maximum=3)

    if cars[chosen_car][0] <= money:
        print(f"Congratulations, you bought a {cars[chosen_car][1]}")
    else:
        print("Unfortunately, you don't have enough money to buy this car")


print("You're about to start a race.")
print("You should buy a car before you start.")
print("Let's see how much you have in your pocket.")
input("> Check your pocket (hit enter to proceed)")
money = int(randint(1,4))
print(f"Oh, you have {money} thousands. Let's see what you can buy with it")
input("> Ok")
choose_a_car()

【讨论】:

  • 它成功了,感谢您为这个问题提供了一个新的视角。
猜你喜欢
  • 2011-05-02
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 2015-06-14
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
相关资源
最近更新 更多