Ситуация: вы пишете простую программу на Python, которая что-то считает по заданному алгоритму. Сначала всё идёт как обычно: объявляется глобальная переменная x, потом делаем новую функцию и обращаемся внутри неё к этой переменной:
x = 10
def sum():
x = x + 5
print(x)
Но при запуске этой функции командой sum() компьютер выдаёт ошибку:
Traceback (most recent call last):
File «main.py», line 6, in
sum()
File «main.py», line 3, in sum
x = x + 5
❌ UnboundLocalError: local variable ‘x’ referenced before assignment
Что это значит: Python ожидает, что x внутри функции будет локальной переменной. Соответственно, он ищет, где она объявляется в функции. А она не объявлена. Python падает с ошибкой.
Когда встречается: когда программист забыл про области видимости переменных или не использовал команду global
.
Что делать с ошибкой UnboundLocalError: local variable referenced before assignment
Главное — определиться с областью видимости и решить, какую переменную вы хотите использовать: локальную или глобальную.
Если вам нужна локальная переменная, то её нужно добавить внутрь функции. Имя переменной при этом может совпадать с именем такой же глобальной переменной, но она никак на неё не повлияет. В этом случае нужно в функцию добавить строку x = <значение>, например:
x = 10
def sum():
x = 11
x = x + 5
# выводим сумму с локальной переменной = 16
print(x)
sum()
# выводим значение глобальной переменной
# оно не поменялось и равно 10
print(x)
Если мы хотим внутри функции работать с глобальной переменной, то её также нужно добавить в функцию командой global
. После этого всё, что мы сделаем внутри функции с этой переменной, будет влиять и на значение глобальной переменной. Работает это так:
x = 10
def sum():
global x
x = x + 5
# выводим сумму с глобальной переменной = 15
print(x)
sum()
# выводим значение глобальной переменной
# оно поменялось и равно 15
print(x)
I don’t like this behavior, but this is how Python works. The question has already been answered by others, but for completeness, let me point out that Python 2 has more such quirks.
def f(x):
return x
def main():
print f(3)
if (True):
print [f for f in [1, 2, 3]]
main()
Python 2.7.6 returns an error:
Traceback (most recent call last):
File "weird.py", line 9, in <module>
main()
File "weird.py", line 5, in main
print f(3)
UnboundLocalError: local variable 'f' referenced before assignment
Python sees the f
is used as a local variable in [f for f in [1, 2, 3]]
, and decides that it is also a local variable in f(3)
. You could add a global f
statement:
def f(x):
return x
def main():
global f
print f(3)
if (True):
print [f for f in [1, 2, 3]]
main()
It does work; however, f becomes 3 at the end… That is, print [f for f in [1, 2, 3]]
now changes the global variable f
to 3
, so it is not a function any more.
Fortunately, it works fine in Python3 after adding the parentheses to print
.
Toggle table of contents sidebar
Распространенные проблемы/нюансы работы с функциями#
Список/словарь в который собираются данные в функции, создан за пределами функции#
Очень часто в решении заданий встречается такой нюанс: функция должна собрать какие-то данные в список/словарь
и список создан вне функции. Тогда вроде как функция работает правильно,
но при этом тест не проходит. Это происходит потому что в таком варианте функция
работает неправильно и каждый вызов добавляет элементы в тот же список:
In [1]: result = [] In [2]: def func(items): ...: for i in items: ...: result.append(i*100) ...: return result ...: In [3]: func([1, 2, 3]) Out[3]: [100, 200, 300] In [4]: func([7, 8]) Out[4]: [100, 200, 300, 700, 800]
Исправить это можно переносом строки создания списка в функцию:
In [20]: def func(items): ...: result = [] ...: for i in items: ...: result.append(i*100) ...: return result ...: In [21]: func([1, 2, 3]) Out[21]: [100, 200, 300] In [22]: func([7, 8]) Out[22]: [700, 800]
Всё, что относится к функции лучше всегда писать внутри функции.
Тест тут не проходит потому что внутри файла задания функция вызывается первый
раз — всё правильно, а потом тест вызывает её второй раз и там вдруг в два раза больше данных чем нужно.
Значения по умолчанию в параметрах создаются во время создания функции#
Пример функции, которая должна выводить текущую дату и время при каждом вызове:
In [1]: from datetime import datetime In [2]: import time In [3]: def print_current_datetime(ptime=datetime.now()): ...: print(f">>> {ptime}") ...: In [4]: for i in range(3): ...: print("Имитируем долгое выполнение...") ...: time.sleep(1) ...: print_current_datetime() ...: Имитируем долгое выполнение... >>> 2021-02-23 09:01:49.845425 Имитируем долгое выполнение... >>> 2021-02-23 09:01:49.845425 Имитируем долгое выполнение... >>> 2021-02-23 09:01:49.845425
Так как datetime.now()
указано в значении по умолчанию,
это значение создается во время создания функции и в итоге при каждом вызове
время одно и то же. Для корректного вывода, надо вызывать datetime.now()
в теле функции:
In [5]: def print_current_datetime(): ...: print(f">>> {datetime.now()}") ...:
Второй пример где этот нюанс может привести к неожиданным результатам,
если о нем не знать — изменяемые типы данных в значении по умолчанию.
Например, использование списка в значении по умолчанию:
In [15]: def add_item(item, data=[]): ...: data.append(item) ...: return data ...:
В этом случае список data создается один раз — при создании функции и
при вызове функции, данные добавляются в один и тот же список.
В итоге все повторные вызовы будут добавлять элементы:
In [16]: add_item(1) Out[16]: [1] In [17]: add_item(2) Out[17]: [1, 2] In [18]: add_item(4) Out[18]: [1, 2, 4]
Если нужно сделать так, чтобы параметр data был необязательным и по умолчанию
создавался пустой список, надо сделать так:
In [22]: def add_item(item, data=None): ...: if data is None: ...: data = [] ...: data.append(item) ...: return data ...: In [23]: add_item(1) Out[23]: [1] In [24]: add_item(2) Out[24]: [2]
Ошибка UnboundLocalError: local variable referenced before assignment#
Ошибка может возникнуть в таких случаях:
-
обращение к переменной в функции идет до ее создания — это может быть
случайность (ошибка) или следствие того, что какое-то условие не выполнилось -
обращение внутри функции к глобальной переменной, но при этом внутри функции
создана такая же переменная позже
Первый случай — обратились к переменной до ее создания:
def f(): print(b) b = 55 In [6]: f() --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) Input In [6], in <cell line: 1>() ----> 1 f() Input In [5], in f() 1 def f(): ----> 2 print(b) 3 b = 55 UnboundLocalError: local variable 'b' referenced before assignment
Переменная создается в условии, а условие не выполнилось:
def f(): if 5 > 8: b = 55 print(b) In [8]: f() --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) Input In [8], in <cell line: 1>() ----> 1 f() Input In [7], in f() 2 if 5 > 8: 3 b = 55 ----> 4 print(b) UnboundLocalError: local variable 'b' referenced before assignment
Имя глобальной и локальной переменной одинаковое и внутри функции сначала идет
попытка обращения к глобальной, потом создание локальной:
a = 10 def f(): print(a) a = 55 print(a) In [4]: f() --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) Input In [4], in <cell line: 1>() ----> 1 f() Input In [3], in f() 1 def f(): ----> 2 print(a) 3 a = 55 4 print(a) UnboundLocalError: local variable 'a' referenced before assignment
Python должен определить область видимости переменной. И в случае функций, Python
считает, что переменная локальная, если она создана внутри функции.
На момент когда мы доходим до вызова функции, Python уже решил, что a
это
локальная переменная и именно из-за этого первая строка print(a)
дает ошибку.
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. |
Local Variable Referenced Before Assignment Error with Explanation
Try these examples yourself using our Online Compiler.
Let’s look at the following function:
# Variable declaration 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
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.
Local variable Referenced before assignment but it is global
This is a common error that happens when we don’t provide a value to a variable and reference it. This can happen with local variables. Global variables can’t be assigned.
This error message is raised when a variable is referenced before it has been assigned a value within the local scope of a function, even though it is a global variable.
Here’s an example to help illustrate the problem:
x = 10 def my_func(): print(x) x += 1 my_func()
In this example, x is a global variable that is defined outside of the function my_func(). However, when we try to print the value of x inside the function, we get a UnboundLocalError with the message “local variable ‘x’ referenced before assignment”.
This is because the += operator implicitly creates a local variable within the function’s scope, which shadows the global variable of the same name. Since we’re trying to access the value of x before it’s been assigned a value within the local scope, the interpreter raises an error.
To fix this, you can use the global keyword to explicitly refer to the global variable within the function’s scope:
x = 10 def my_func(): global x print(x) x += 1 my_func()
However, in the above example, the global keyword tells Python that we want to modify the value of the global variable x, rather than creating a new local variable. This allows us to access and modify the global variable within the function’s scope, without causing any errors.
Local variable ‘version’ referenced before assignment ubuntu-drivers
This error occurs with Ubuntu version drivers. To solve this error, you can re-specify the version information and give a split as 2 –
version = int(p_name.split('-')[-2])
Here, p_name means package name.
FAQs
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.
What is UnboundLocalError?
When a variable that is created locally is called before assigning, it results in Unbound Local Error in Python. The interpreter can’t track the variable.
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
-
[Solved] typeerror: unsupported format string passed to list.__format__
●May 31, 2023
-
Solving ‘Remote End Closed Connection’ in Python!
by Namrata Gulati●May 31, 2023
-
[Fixed] io.unsupportedoperation: not Writable in Python
by Namrata Gulati●May 31, 2023
-
[Fixing] Invalid ISOformat Strings in Python!
by Namrata Gulati●May 31, 2023
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!