Unbound local error

If you try to reference a local variable before assigning a value to it within the body of a function, you will encounter the UnboundLocalError: local

If you try to reference a local variable before assigning a value to it within the body of a function, you will encounter the UnboundLocalError: local variable referenced before assignment.

The preferable way to solve this error is to pass parameters to your function, for example:

test_var = 0

def test_func(test_var):
    test_var += 1
    return test_var

test_func(test_var)

Alternatively, you can declare the variable as global to access it while inside a function. For example,

test_var = 0

def test_func():
    global test_var
    test_var += 1
    return test_var

test_func()

This tutorial will go through the error in detail and how to solve it with code examples.


Table of contents

  • What is Scope in Python?
  • UnboundLocalError: local variable referenced before assignment
  • Example #1: Accessing a Local Variable
    • Solution #1: Passing Parameters to the Function
    • Solution #2: Use Global Keyword
  • Example #2: Function with if-elif statements
    • Solution #1: Include else statement
    • Solution #2: Use global keyword
  • Summary

What is Scope in Python?

Scope refers to a variable being only available inside the region where it was created. A variable created inside a function belongs to the local scope of that function, and we can only use that variable inside that function.

A variable created in the main body of the Python code is a global variable and belongs to the global scope. Global variables are available within any scope, global and local.

UnboundLocalError: local variable referenced before assignment

UnboundLocalError occurs when we try to modify a variable defined as local before creating it. If we only need to read a variable within a function, we can do so without using the global keyword. Consider the following example that demonstrates a variable var created with global scope and accessed from test_func:

var = 10

def test_func():
    print(var)

test_func()
10

If we try to assign a value to var within test_func, the Python interpreter will raise the UnboundLocalError:

var = 10

def test_func():
    var += 1
    print(var)
test_func()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [17], in <cell line: 6>()
      4     var += 1
      5     print(var)
----> 6 test_func()

Input In [17], in test_func()
      3 def test_func():
----> 4     var += 1
      5     print(var)

UnboundLocalError: local variable 'var' referenced before assignment

This error occurs because when we make an assignment to a variable in a scope, that variable becomes local to that scope and overrides any variable with the same name in the global or outer scope.

var +=1 is similar to var = var + 1, therefore the Python interpreter should first read var, perform the addition and assign the value back to var.

var is a variable local to test_func, so the variable is read or referenced before we have assigned it. As a result, the Python interpreter raises the UnboundLocalError.

Example #1: Accessing a Local Variable

Let’s look at an example where we define a global variable number. We will use the increment_func to increase the numerical value of number by 1.

number = 10

def increment_func():
    number += 1
    return number

print(increment_func())

Let’s run the code to see what happens:

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [19], in <cell line: 7>()
      4     number += 1
      5     return number
----> 7 print(increment_func())

Input In [19], in increment_func()
      3 def increment_func():
----> 4     number += 1
      5     return number

UnboundLocalError: local variable 'number' referenced before assignment

The error occurs because we tried to read a local variable before assigning a value to it.

Solution #1: Passing Parameters to the Function

We can solve this error by passing a parameter to increment_func. This solution is the preferred approach. Typically Python developers avoid declaring global variables unless they are necessary. Let’s look at the revised code:

number = 10

def increment_func(number):

    number += 1

    return number

print(increment_func(number))

We have assigned a value to number and passed it to the increment_func, which will resolve the UnboundLocalError. Let’s run the code to see the result:

11

We successfully printed the value to the console.

Solution #2: Use Global Keyword

We also can solve this error by using the global keyword. The global statement tells the Python interpreter that inside increment_func, the variable number is a global variable even if we assign to it in increment_func. Let’s look at the revised code:

number = 10

def increment_func():

    global number

    number += 1

    return number

print(increment_func())

Let’s run the code to see the result:

11

We successfully printed the value to the console.

Example #2: Function with if-elif statements

Let’s look at an example where we collect a score from a player of a game to rank their level of expertise. The variable we will use is called score and the calculate_level function takes in score as a parameter and returns a string containing the player’s level.

score = int(input("Enter your score between 0 and 100: "))

def calculate_level(score):

    if score > 90:

        level = 'expert'

    elif score > 70:

        level = 'advanced'

    elif score > 55:

        level = 'intermediate'

    return level

In the above code, we have a series of if-elif statements for assigning a string to the level variable. Let’s run the code to see what happens:

print(f'Your level is: {calculate_level(score)}')
Enter your score between 0 and 100: 40

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [12], in <cell line: 1>()
----> 1 print(f'Your level is: {calculate_level(score)}')

Input In [11], in calculate_level(score)
      7 elif score > 55:
      8     level = 'intermediate'
----> 9 return level

UnboundLocalError: local variable 'level' referenced before assignment

The error occurs because we input a score equal to 40. The conditional statements in the function do not account for a value below 55, therefore when we call the calculate_level function, Python will attempt to return level without any value assigned to it.

Solution #1: Include else statement

We can solve this error by completing the set of conditions with an else statement. The else statement will provide an assignment to level for all scores lower than 55. Let’s look at the revised code:

score = int(input("Enter your score between 0 and 100: "))

def calculate_level(score):

    if score > 90:

        level = 'expert'

    elif score > 70:

        level = 'advanced'

    elif score > 55:

        level = 'intermediate'

    else:

        level = 'beginner'

    return level

In the above code, all scores below 55 are given the beginner level. Let’s run the code to see what happens:

print(f'Your level is: {calculate_level(score)}')
Enter your score between 0 and 100: 40

Your level is: beginner

Solution #2: Use global keyword

We can also create a global variable level and then use the global keyword inside calculate_level. Using the global keyword will ensure that the variable is available in the local scope of the calculate_level function. Let’s look at the revised code.

score = int(input("Enter your score between 0 and 100: "))

level = 'beginner'

def calculate_level(score):

    global level

    if score > 90:

        level = 'expert'

    elif score > 70:

        level = 'advanced'

    elif score > 55:

        level = 'intermediate'

    return level

In the above code, we put the global statement inside the function and at the beginning. Note that the “default” value of level is beginner and we do not include the else statement in the function. Let’s run the code to see the result:

print(f'Your level is: {calculate_level(score)}')
40 

Your level is: beginner

Summary

Congratulations on reading to the end of this tutorial! The UnboundLocalError: local variable referenced before assignment occurs when you try to reference a local variable before assigning a value to it. Preferably, you can solve this error by passing parameters to your function. Alternatively, you can use the global keyword.

If you have if-elif statements in your code where you assign a value to a local variable and do not account for all outcomes, you may encounter this error. In which case, you must include an else statement to account for the missing outcome.

For further reading on Python code blocks and structure, go to the article: How to Solve Python IndentationError: unindent does not match any outer indentation level.

Go to the online courses page on Python to learn more about Python for data science and machine learning.

Have fun and happy researching!

As a new Python programmer, I ran into three common language gotchas: passing variables by reference, unbound local errors, and mutable default arguments. Hopefully this post will help shed some light on these gotchas and save you the time I spent debugging them. However, what I gained by attempting to understand these gotchas was a wonderful opportunity to take a deep dive into a new language and explore some of its under-the-hood behavior.


Passing By Reference

I encountered the pass-by-reference gotcha when I first tried to play the game loop. My game was able to ask the user for input, set the size of the board, create a board, and accurately create a human and computer player. However, when I tried to place the first move, my move was not marked in the one square I had picked, but in three squares.

My game was marking the entire column.

In other words, instead of looking like the image on the left, my board looked like the image on the right:

After some research and debugging, I discovered that this behavior was thanks to Python’s pass by reference characteristic. My board had been created using the following function:

[[None * row_size] * row_size] 

Here when creating a board with a row_size of 3, one might expect to get 9 distinct None objects. However, when building the board using this function in Python, we start off with a reference to a list, and then replicate that reference 3 times. Hence when we change the value in one of the lists, we change the value in all 3 lists.

None itself is Python’s null equivalent. For more about None see the section directly below.

A Brief Look At None In Python

  • None is an object — or to be more specific, a Singleton class. Not a primitive type, such as int, or True and False.
  • In Python 3.x, the type object was changed from type ‘NoneType’ to class ‘NoneType’. However the behaviour of None has remained the same from 2.x to 3.x.
  • Because None is an object, we cannot use it to check if a variable exists. It is a value/object, not an operator used to check a condition.

    In this REPL—Click on the Play button to run tests, or toggle lines 24 and 25, and then run the code to view the Pass-by-Reference gotcha

Python Scope

To discuss Unbound Local Errors, I thought it might be helpful to touch upon Python scoping first. Scoping in Python follows the LEGB Rule: Local -> Enclosed
-> Global -> Built-in.
Here we work our way from the inside out, from local to built-in.

posts/2019-05-07-some-common-gotchas-in-python/legb.png

  • Local scope refers to a variable that is defined within a function body. A variable is always checked for in local scope first.
    In the repl below, if we toggle the lines of code so that line 8 is off, we’ll see that our outer function executes and prints the local version of variable my_var, returning a value of my inner/local variable.
  • Enclosed scope is created when a function wraps another function—here the outer function is the enclosing scope. Back in our repl, we can now comment line 7 and uncomment line 8. On line 8, the nonlocal keyword will now point Python to using the variable initialized on line 5, in the outer enclosing scope. Thus we will see my enclosed variable printed to the console.
  • Global—as we can imagine, variables assigned at the top-level of a module file are global in scope. line 13 of the repl prints my_var from line 2, as it is unable to access the various other instantiations of my_var that are all within enclosed or local scopes. Similar to the nonlocal keyword, we can use the global keyword to initialize a variable to the global scope from an enclosed or local context.
  • Built-ins—no surprises here either, built-ins refer to names preassigned in Python’s built-in names module, such as Math, open, range, and SyntaxError.

    In this REPL—Click on the Play button to run tests, or toggle lines 15, 24, and 25, and then run the code to learn more about how Python’s LEGB scoping works


Unbound Local Error

Let’s say we define a variable my_var in the global scope and set it to 5. If we then create a function and attempt to assign a new value to the same variable, but within the function’s local context, we’ll get an UnboundLocalError returned to us.
The above error occurs because, when we make an assignment to a variable in scope, that variable becomes local to that scope and shadows any similarly named variable in the outer scope. In the context of the repl below, on line 7 we are in effect initializing a new variable my_var to a value of += 1, and an error is generated. This error is particularly common when working with lists, as shown in the last example in the repl, and one way to solve accessing a variable declared in the global context is to refer to it as global, as seen in the method on line 10 of the repl.

In this REPL—Click on the Play button to run tests, or edit the code in functions bar and foo2 to play with Unbound Local Errors


Mutable Default Arguments

For my second bug, a gotcha showed up in my implementation of the Minimax algorithm. My code was displaying some strange behavior.

My first test was set up to check that Minimax chose the only open spot, in this case a 5.

After that, the next test checked if, when given a choice between two open spots, Minimax selected the winning move as opposed to a blocking move. In this case the open spots were 8 and 9, counting from a 1-indexed array.

A third test checked whether, when given a choice of multiple open spots, Minimax still chose the winning move. Here the open spots in the 1-indexed array included 4, 6, 7, 8, 9.

Strangely enough, 5 kept showing up as the selected move in all three of these tests, even though 5 was only a valid option in my very first test, and not a valid option in the other two mentioned. It looked like the open spot from my first test was somehow persisting into my next two tests.

Here my mentor alerted me to read up on Python Gotchas, of which Mutable Default Arguments1 was one.

According to the article,

A new list is created once when the function is defined, and the same list is used in each successive call.

Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.

Here was the offending line itself:

def minimax(self, game, depth=0, scores_map={}): 

The same goes for any default arguments in a function call that are set to mutable data types in Python. A quick search for mutable types in Python tells us:

Objects of built-in types like int, float, bool, str, tuple, and unicode are immutable. Objects of built-in types like list, set, and dict are mutable. Custom classes are generally mutable.

A table to illustrate might be simpler, see below.2

My scores map was being mutated with a 5 the first time it was called and then it held on to the 5 for all future calls to that function as well.

To avoid this common gotcha, the trick was to adjust my code to initialize the scores map variable to None instead of an empty dictionary in the function call, and then to check if scores_map needed to be initialized later within the body of the function:

def minimax(self, game, depth=0, scores_map=None):
 if not scores_map: 
 scores_map = {} 

In this REPL—Click on the Play button to run tests, or toggle the multiple tests on each of the map and array methods to view how this quirk is triggered


Mutable & Immutable Types In Python

Class Description Immutable Mutable
bool Boolean value x
int Integer (arbitrary magnitude) x
float floating-point number x
list Mutable sequence of objects x
tuple Immutable sequence of objects x
str Character string x
set Unordered set of distinct objects x
frozenset Immutable form of set class x
dict Dictionary/Associative mapping x

The “local variable referenced before assignment” error occurs when you give reference of a local variable without assigning any value.

Example:

v1 = 1
def myfunction():
    if v1 == 0:
        print("Value: Zero")
    elif v1 == 1:
        print("Value: One")
    elif v1 >= 2:
        print("Value: Greater then 1")
    v1 = 0
    
myfunction()

Output:

UnboundLocalError: local variable “v1” referenced before assignment

Explanation:

In the above example, we have given the value of variable “v1” in two places.

  • Outside the function “myfunction()”.
  • And at the end of the function “myfunction()”.

If we assign a value of a variable in the function it becomes local variable to that function, but in the above example we have assigned the value to “v1” variable at the end of the function and we are referring this variable before assigning.

And the variable“v1” which we have assigned at the beginning of the code block is not declared as a global variable.

Solutions:

To avoid an error like “UnboundLocalError: local variable referenced before assignment” to occur, we have to:

  • Declare GLOBAL variable
  • Pass parameters with the function

Declare Global Variable

Code example with global variable:

v1 = 1
def myfunction():
    global v1

    if v1 == 0:
        print("Value: Zero")
    elif v1 == 1:
        print("Value: One")
    elif v1 >= 2:
        print("Value: Greater then 1")
    
myfunction()

Output:

Value: One

Explanation:

As we know if we declare any variable as global then its scope becomes global.

Pass function with Parameters

Code example passing parameters with function:

def myfunction(v1):
    if v1 == 0:
        print("Value: Zero")
    elif v1 == 1:
        print("Value: One")
    elif v1 >= 2:
        print("Value: Greater then 1")
    
myfunction(10)

Output:

Value: Greater then 1

Explanation:

In the above example, as you can see, we are not using a global variable but passing the value of variable “v1” as a parameter with the function “myfunction()”.

Example 2

def dayweek(day):
    if day == 7 or day == 6 or day == 0:
        wd = 'Weekend'
    elif day >= 1 and day <= 5:
        wd = 'Weekday'
    return wd
    
print(dayweek(10))

Output:

UnboundLocalError: local variable 'wd' referenced before assignment

Example 2.1

def dayweek(day):
    if day == 7 or day == 6 or day == 0:
        wd = 'Weekend'
    elif day >= 1 and day <= 5:
        wd = 'Weekday'
    return wd
    
print(dayweek(1))

Output:

Weekday

In the «example2«, we have called a function “dayweek()” with parameter value “10” which gives the error but the same function with value “1” which runs properly in “example 2.1” and returns the output as “Weekday”.

Because in the above function we are assigning the value to variable “wd” if the value of variable «day» is the range from (0 to 7). If the value of variable «day» greater than «7» or lower then «0″ we are not assigning any value to variable «wd» That’s why, whenever the parameter is greater than 7 or less than 0, python compiler throws the error “UnboundLocalError: local variable ‘wd’ referenced before assignment

To avoid such type of error you need assign the function variable which lies within the range or we need to assign some value like «Invalid Value» to variable «wd» if the value of variable «day» is not in range from (0 to 7)

Correct Example with Exception

def dayweek(day):
    if day == 7 or day == 6 or day == 0:
        wd = 'Weekend'
    elif day >= 1 and day <= 5:
        wd = 'Weekday'
    else:
        wd = 'Invalid Value'
    return wd
    
print(dayweek(22))

Python treats variables referenced only inside a function as global variables. Any variable assigned to a function’s body is assumed to be a local variable unless explicitly declared as global.

Why Does This Error Occur?

Unboundlocalerror: local variable referenced before assignment occurs when a variable is used before its created. Python does not have the concept of variable declarations. Hence it searches for the variable whenever used. When not found, it throws the error.

Before we hop into the solutions, let’s have a look at what is the global and local variables.

Local Variable Declarations vs. Global Variable Declarations

Local Variables Global Variables
A local variable is declared primarily within a Python function. Global variables are in the global scope, outside a function.
A local variable is created when the function is called and destroyed when the execution is finished. A Global Variable is created upon execution and exists in memory till the program stops.
Local Variables can only be accessed within their own function. All functions of the program can access global variables.
Local variables are immune to changes in the global scope. Thereby being more secure. Global Variables are less safer from manipulation as they are accessible in the global scope.

“Other Commands Don’t Work After on_message” in Discord Bots

Local Variable Referenced Before Assignment Error with Explanation

Try these examples yourself using our Online Compiler.

Let’s look at the following function:

# Variable decleration outside function (global scope)
myVar = 10


def myFunction():
      if myVar == 5:
            print("5")
      elif myVar == 10:
            print("10")
      elif myVar >= 15:
            print("greater than 15 ")
     # reassigning myVar in the function
      myVar = 0

myFunction()

Output

Local Variable Referenced Before Assignment Error

Explanation

The variable myVar has been assigned a value twice. Once before the declaration of myFunction and within myFunction itself.

Solutions

Using Global Variables

Passing the variable as global allows the function to recognize the variable outside the function.

myVar = 10
def myFunction():
     # Telling the function to consider myVar as global
      global myVar
      if myVar == 5:
            print("5")
      elif myVar == 10:
            print("10")
      elif myVar >= 15:
            print("greater than 15 ")
      myVar = 0

myFunction()

Output

10

Create Functions that Take in Parameters

Instead of initializing myVar as a global or local variable, it can be passed to the function as a parameter. This removes the need to create a variable in memory.

# Passing myVar as a parameter in the function
def myFunction(myVar):
      if myVar == 5:
            print("5")
      elif myVar == 10:
            print("10")
      elif myVar >= 15:
            print("greater than 15 ")
      myVar = 0

myFunction(10)

Output

10

UnboundLocalError: local variable ‘DISTRO_NAME’

This error may occur when trying to launch the Anaconda Navigator in Linux Systems.

Upon launching Anaconda Navigator, the opening screen freezes and doesn’t proceed to load.

$ anaconda-navigator          
Traceback (most recent call last):
  File "/home/user/anaconda3/lib/python3.7/site-packages/anaconda_navigator/widgets/main_window.py", line 541, in setup
    self.post_setup(conda_data=conda_data)
...
...
UnboundLocalError: local variable 'DISTRO_NAME' referenced before assignment

Solution 1

Try and update your Anaconda Navigator with the following command.

conda update anaconda-navigator

Solution 2

If solution one doesn’t work, you have to edit a file located at

.../anaconda3//lib/python3.7/site-packages/anaconda_navigator/api/external_apps/vscode.py

After finding and opening the Python file, make the following changes:

In the function on line 159, simply add the line:

DISTRO_NAME = None

Save the file and re-launch Anaconda Navigator.

The program takes information from a form filled out by a user. Accordingly, an email is sent using the information.

from django import forms


# Creating a Class for django forms
class MyForm(forms.Form):
    name = forms.CharField(required=True)
    email = forms.EmailField(required=True)
    msg = forms.CharField(
        required=True,
        widget=forms.Textarea
    )


...
# Create a function to retrieve info from the form
def GetContact(request):
    form_class = ContactForm
    if request.method == 'POST':
        form = form_class(request.POST)

        # Upon verifying validity, get following info and email with said info
        if form.is_valid():
            name = request.POST.get('name')
            email = request.POST.get('email')
            msg = request.POST.get('msg')

            send_mail('Subject here', msg, email, ['[email protected]'], fail_silently=False)
            return HttpResponseRedirect('blog/inicio')
            return render(request, 'blog/inicio.html', {'form': form})
...

Upon running you get the following error:

local variable 'form' referenced before assignment

Explanation

We have created a class myForm that creates instances of Django forms. It extracts the user’s name, email, and message to be sent.

A function GetContact is created to use the information from the Django form and produce an email. It takes one request parameter. Prior to sending the email, the function verifies the validity of the form. Upon True, .get() function is passed to fetch the name, email, and message. Finally, the email sent via the send_mail function

Why does the error occur?

We are initializing form under the if request.method == “POST” condition statement. Using the GET request, our variable form doesn’t get defined.

FAQs on Local Variable Referenced Before Assignment

How would you avoid using a global variable in multi-threads?

With the help of the threading module, you can avoid using global variables in multi-threading. Make sure you lock and release your threads correctly to avoid the race condition.

Conclusion

Therefore, we have examined the local variable referenced before the assignment Exception in Python. The differences between a local and global variable declaration have been explained, and multiple solutions regarding the issue have been provided.

Trending Python Articles

  • “Other Commands Don’t Work After on_message” in Discord Bots

    “Other Commands Don’t Work After on_message” in Discord Bots

    February 5, 2023

  • Botocore.Exceptions.NoCredentialsError: Unable to Locate Credentials

    Botocore.Exceptions.NoCredentialsError: Unable to Locate Credentials

    by Rahul Kumar YadavFebruary 5, 2023

  • [Resolved] NameError: Name _mysql is Not Defined

    [Resolved] NameError: Name _mysql is Not Defined

    by Rahul Kumar YadavFebruary 5, 2023

  • Best Ways to Implement Regex New Line in Python

    Best Ways to Implement Regex New Line in Python

    by Rahul Kumar YadavFebruary 5, 2023

Понравилась статья? Поделить с друзьями:
  • Unb ошибка на стиральной машине haier что это означает
  • Unb ошибка на стиральной машине haier как сбросить
  • Unavailable database error
  • Unauthorized wireless network card is plugged in power off and remove it lenovo как исправить
  • Unauthorized access error message