Piotr Menclewicz
Piotr Menclewicz

Reputation: 109

Python - UnboundLocalError: local variable referenced before assignment in a loop

I'm a newbie in Python and I'm trying to do an excersise from Zed Shaw's book. I've tried to find an answer for my question and debug the code on my own but with no success.

I'm getting "local variable referenced before assignement" error but only after looping one of the branches. E.g. when I choose non-integer character in my input (chosen_car = int(input("> "))) the function should start from the beginning and allow me to choose a correct value. But when I choose the correct number after that I get an error. In a shell it look like this:

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

Here's the code. I'll be very helpful for your help.

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!")

Upvotes: 0

Views: 1791

Answers (4)

G_M
G_M

Reputation: 3372

You could do something like this:

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

Upvotes: 0

Alperen G&#246;rmez
Alperen G&#246;rmez

Reputation: 392

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

This code snippet uses recursion. Therefore, if the user enters an invalid input, the program enters the except block and calls the function again. And if the user enters a correct number in the second call, the second call terminates successfully and you turn back to the first function call. However, in the first call, chosen_car is not defined because of the invalid input. Therefore the program crashes with the error. Instead of recursion, you can try to use a flag as follows:

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

By doing this, if the program crashes in chosen_car = int(input("> ")) line, myFlag is not set to False and the program continues to get inputs from the user.

I have not checked the code, but I suppose that should work.

Upvotes: 1

whackamadoodle3000
whackamadoodle3000

Reputation: 6748

Here is your problem:

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 this goes into the except, then chosen car won't be defined. I suggest you define it outside of the try, or put the entire thing inside of a while loop instead of recursing with the choose_a_car().

Upvotes: 0

polarise
polarise

Reputation: 2413

Initialise chosen_car by setting it to None before the try statement. You are getting the exception because by the time you get to line 17 that variable has not been initialised.

Upvotes: 0

Related Questions