Python 3: UnboundLocalError: local variable referenced before assignment
You can fix this by passing parameters rather than relying on Globals
def function(Var1, Var2):
if Var2 == 0 and Var1 > 0:
print("Result One")
elif Var2 == 1 and Var1 > 0:
print("Result Two")
elif Var1 < 1:
print("Result Three")
return Var1 -= 1
function(1, 1)
Python scope: UnboundLocalError: local variable 'c' referenced before assignment
Within a function, variables that are assigned to are treated as local variables by default. To assign to global variables, use the global
statement:
def g(n):
global c
c = c + n
This is one of the quirky areas of Python that has never really sat well with me.
UnboundLocalError: local variable function referenced before assignment
Whether a name used in a function is a global variable or a local one is determined at compile time, not at run time. Your functions that cause exceptions are trying to have it both ways, to either access a global, or provide their own local variable replacement, but Python's scoping rules don't allow that. It needs to be local or global, and can't be in a nebulous either/or state.
In your Test 1, the function raises an exception because the compiler saw that the code could assign to take_sum
as a local variable, and so it makes all the references to take_sum
in the code be local. You can no longer look up the global variable take_sum
in the normal way once that determination has been made.
A global
statement is in effect a compiler directive to change the assumption that an assignment makes a variable local. Subsequent assignments will be made globally, not locally. It's not something that executes at runtime, which is why your other two test cases are so confusing to you.
Test 2 fails because you're trying to tell the compiler that take_sum
is a global after it has already seen some of your code make a local assignment to that name. In Test 3, the global
statement comes first, so it makes the assignment (in the other branch!) assign to a global variable. It doesn't actually matter that the global
statement was in a different branch than the assignment, the compiler interprets the global
statement at compile time, not at runtime when the conditional logic of the if
s and elif
s gets handled.
It might help your understanding of what is going on to disassemble some of the main
functions you've written using the dis.dis
function in the standard library. You'll see that there are two different sets of bytecodes used for loading and storing of variables, LOAD_GLOBAL
/STORE_GLOBAL
for global variables (used in all your functions to get names like print
and globals
), and LOAD_FAST
/STORE_FAST
which are used for local variables (like a
, b
and c
in take_sum
). The compiler behavior I talked about above boils down to which bytecode it chooses for each lookup or assignment.
If I rename the main
function in Test 1 to test1
, here's what I get when I disassemble it:
dis.dis(test1)
2 0 LOAD_CONST 1 ('take_sum')
2 LOAD_GLOBAL 0 (globals)
4 CALL_FUNCTION 0
6 CONTAINS_OP 1
8 POP_JUMP_IF_FALSE 18
3 10 LOAD_CONST 2 (<code object <lambda> at 0x0000019022A05F50, file "<ipython-input-23-0cc3c65f7038>", line 3>)
12 LOAD_CONST 3 ('test1.<locals>.<lambda>')
14 MAKE_FUNCTION 0
16 STORE_FAST 0 (take_sum)
5 >> 18 LOAD_GLOBAL 1 (print)
20 LOAD_FAST 0 (take_sum)
22 CALL_FUNCTION 1
24 POP_TOP
26 LOAD_CONST 0 (None)
28 RETURN_VALUE
Disassembly of <code object <lambda> at 0x0000019022A05F50, file "<ipython-input-23-0cc3c65f7038>", line 3>:
3 0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_ADD
6 LOAD_FAST 2 (c)
8 BINARY_ADD
10 RETURN_VALUE
Notice that the lookup of take_sum
on line 5 is on byte 20 in the bytecode, where it uses LOAD_FAST
. This is the bytecode that causes the UnboundLocalError
, since there has been no local assigned if the global function exists.
Now, lets look at Test 3:
dis.dis(test3)
2 0 LOAD_CONST 1 ('take_sum')
2 LOAD_GLOBAL 0 (globals)
4 CALL_FUNCTION 0
6 CONTAINS_OP 0
8 POP_JUMP_IF_FALSE 12
3 10 JUMP_FORWARD 18 (to 30)
5 >> 12 LOAD_CONST 1 ('take_sum')
14 LOAD_GLOBAL 0 (globals)
16 CALL_FUNCTION 0
18 CONTAINS_OP 1
20 POP_JUMP_IF_FALSE 30
6 22 LOAD_CONST 2 (<code object <lambda> at 0x0000019022A43500, file "<ipython-input-26-887b66de7e64>", line 6>)
24 LOAD_CONST 3 ('test3.<locals>.<lambda>')
26 MAKE_FUNCTION 0
28 STORE_GLOBAL 1 (take_sum)
8 >> 30 LOAD_GLOBAL 2 (print)
32 LOAD_GLOBAL 1 (take_sum)
34 CALL_FUNCTION 1
36 POP_TOP
9 38 LOAD_GLOBAL 2 (print)
40 LOAD_GLOBAL 1 (take_sum)
42 LOAD_CONST 4 (1)
44 LOAD_CONST 5 (2)
46 LOAD_CONST 6 (3)
48 CALL_FUNCTION 3
50 CALL_FUNCTION 1
52 POP_TOP
54 LOAD_CONST 0 (None)
56 RETURN_VALUE
Disassembly of <code object <lambda> at 0x0000019022A43500, file "<ipython-input-26-887b66de7e64>", line 6>:
6 0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_ADD
6 LOAD_FAST 2 (c)
8 BINARY_ADD
10 RETURN_VALUE
This time the lookup of take_sum
happens on bytecode 40, and it's a LOAD_GLOBAL
(which succeeds since there is a global variable of that name).
Local variable referenced before assignment?
When Python parses the body of a function definition and encounters an assignment such as
feed = ...
Python interprets feed
as a local variable by default. If you do not wish for it to be a local variable, you must put
global feed
in the function definition. The global statement does not have to be at the beginning of the function definition, but that is where it is usually placed. Wherever it is placed, the global declaration makes feed
a global variable everywhere in the function.
Without the global statement, since feed
is taken to be a local variable, when Python executes
feed = feed + 1,
Python evaluates the right-hand side first and tries to look up the value of feed. The first time through it finds feed
is undefined. Hence the error.
The shortest way to patch up the code is to add global feed
to the beginning of onLoadFinished
. The nicer way is to use a class:
class Page(object):
def __init__(self):
self.feed = 0
def onLoadFinished(self, result):
...
self.feed += 1
The problem with having functions which mutate global variables is that it makes it harder to grok your code. Functions are no longer isolated units. Their interaction extends to everything that affects or is affected by the global variable. Thus it makes larger programs harder to understand.
By avoiding mutating globals, in the long run your code will be easier to understand, test and maintain.
python giving me UnboundLocalError: local variable referenced before assignment when trying to work with variables
According to Python documentation, if the compiler sees a variable assignment in a function/method (local scope), it will automatically mark that name as local and hence not consider any similarly named outside variables. That is why, when it sees that before assignment of the local variable it is used inside function for something else (to check a condition in your case), it will throw an error that you actually are trying to use a variable which has not been assigned yet (in local terms).
If you changed lives = lives - 1
to new_lives = lives - 1
, then the compiler would treat lives
as a global variable and not throw an Exception. But this would create more problems in your case. I suggest passing lives as an argument to the function - def boss(lives):
and call it in your loop by passing lives boss(lives)
.
UnboundLocalError: local variable 'x' referenced before assignment for one variable whilst other works in Python
It is because for copy_matrix
there is no local variable there, so it references the nonlocal
variable present at line 6 ie copy_matrix = {}
, while for cur_max
it is being defined as a local variable in line 24 ie cur_max = max(cur_max, copy_matrix[(r, c)])
, it is referencing nonlocal variables for copy_matirx
, rows
, columns
but it is referencing the local variable for cur_max
because it is being defined in the function and being referenced before assignment. What you probably want to do is this
def dfs(r, c, prev):
nonlocal cur_max
if (r < 0 or c < 0 or
r == rows or c == columns or
matrix[r][c] <= prev):
return 0
if (r, c) in copy_matrix:
return copy_matrix[(r, c)]
max_length = 0
max_length = max(max_length, 1 + dfs(r + 1, c, matrix[r][c]))
max_length = max(max_length, 1 + dfs(r - 1, c, matrix[r][c]))
max_length = max(max_length, 1 + dfs(r, c + 1, matrix[r][c]))
max_length = max(max_length, 1 + dfs(r, c - 1, matrix[r][c]))
copy_matrix[(r, c)] = max_length
cur_max = max(cur_max, copy_matrix[(r, c)])
return max_length
read more
UnboundLocalError: local variable 'temperature' referenced before assignment in the member function after creating a constructor?
After looking at your code, I noticed that you are trying to access self.temperature
using just temperature
.
The first argument each method receives (self
) is a reference of the object itself, and is used to access object attributes and methods.
UnboundLocalError: local variable 'settingsText' referenced before assignment
You should call global
before you use the variable :
global settingsText
settingsMenu = input(settingsText)
also you'll have the same problem with variables like length
.
Related Topics
How to Dynamically Load a Python Class
Is There Any Simple Way to Benchmark Python Script
Dropping Infinite Values from Dataframes in Pandas
Python: Change the Scripts Working Directory to the Script's Own Directory
Differencebetween Using Loc and Using Just Square Brackets to Filter for Columns in Pandas/Python
How to Add a New Column to a Spark Dataframe (Using Pyspark)
Python Request Post with Param Data
Pip or Pip3 to Install Packages for Python 3
Deep-Learning Nan Loss Reasons
Integrating MySQL with Python in Windows
How to Filter a Date of a Datetimefield in Django
How to Add a Custom Ca Root Certificate to the Ca Store Used by Pip in Windows
Pandas Dataframe Concat VS Append