Python Forum

Full Version: How to fix UnboundLocalError
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
The code below models a simple game that tests if an input occurs in the list. The function is called twice, then the total # of correct answers is printed.

foot_bones = ["calcaneus", "talus", "cuboid", "navicular", "lateral cuneiform", "intermediate cuneiform", "medial cuneiform"]
answers_right = 0

def finder(bone_name):
    if bone_name.lower() in foot_bones:
        print("correct!")
        answers_right += + 1
    else:
        print("incorrect")
        
finder(input("enter name of a bone: "))
finder(input("enter name of another bone: "))

print("number of foot bones correctly identified: ", answers_right)
Code returns no error when the input is "incorrect", but gives an UnboundLocalError when a correct one is passed. How do I fix it? Simple issue.

Thanks!
You have an extra "+" in line 7

        answers_right += 1
When a variable such as answers_right is on the left hand side of an assignment operator in a function, it becomes a local variable of this function. It means that the answers_right variable in function finder() is not the same as the global variable answers_right. Python complains because you are incrementing the local variable when this variable doesn't yet have a value.

A way to solve this is to add the statement global answers_right at the top of the finder()'s function body.

It is good practice to avoid global statements in python code, because they obfuscate the code somewhat, but they are allowed.
(Jan-07-2018, 08:08 AM)Gribouillis Wrote: [ -> ]It is good practice to avoid global statements in python code, because they obfuscate the code somewhat, but they are allowed.

Thanks! That fixed it.

No need to answer further, but would you recommend a different method of keeping track of the answers_right, without resorting to a global variable?
Using global variables is not recommended.
You can do the same by passing answers_right as an argument to the function.

def finder(bone_name, correct):
    if bone_name.lower() in foot_bones:
        print("correct!")
        correct += 1
    else:
        print("incorrect")
Then call the function.
bone_name = input("enter name of a bone: ")
finder(bone_name, answers_right)
print(answers_right)
(Jan-07-2018, 04:16 PM)Tawnwen Wrote: [ -> ]would you recommend a different method of keeping track of the answers_right, without resorting to a global variable?
You are reaching the point where you have functions that manipulate external data and you need a way to manage both the data and the function. That's why classes were invented. Here is how you can code this by using a class:

class BoneFinder:
    foot_bones = [
        "calcaneus", "talus", "cuboid",
        "navicular", "lateral cuneiform",
        "intermediate cuneiform", "medial cuneiform",
    ]

    def __init__(self):
        self.answers_right = 0
 
    def examine(self, bone_name):
        if bone_name.lower() in self.foot_bones:
            print("correct!")
            self.answers_right += + 1
        else:
            print("incorrect")

finder = BoneFinder()         
finder.examine(input("enter name of a bone: "))
finder.examine(input("enter name of another bone: "))
 
print("number of foot bones correctly identified: ", finder.answers_right)
In this code, a single entity holds the variable answer_right between subsequent calls. The code looks more complicated than your program but in fact, it is easier to extend by adding new features.