unboundlocalerror local variable 'i' referenced before assignment - python

I'm new in python trying to execute this code:
def dubleIncrement():
j = j+2
def increment():
i = i+1
dubleIncrement()
if __name__ == "__main__":
i = 0
j = 0
increment()
print i
print j
But getting this error :
unboundlocalerror local variable 'i' referenced before assignment
Anybody has any idea why i is not global

Declare global keyword inside your functions to access the global as opposed to local variable. i.e.
def dubleIncrement():
global j
j = j+2
def increment():
global i
i = i+1
Note that when you declare i = 0 and j = 0 in your if statement, this is setting a global variable, but since it is outside the scope of any functions, the global keyword is not necessary to use here.
Ideally, you should try to stay away from using global variables as much as possible and try to pass variables as parameters to functions (think about what happens when you decide to use the variable names i and j again in some other function-- ugly collisions could occur!). The following would be one much safer way to write your code:
def dubleIncrement(x):
x = x+2
return x
def increment(x):
x = x+1
return x
if __name__ == "__main__":
i = 0
j = 0
i = increment(i)
j = dubleIncrement(j)
print i
print j

Related

How to change the global value of a parameter when using a function in python

This is what I want to achieve
Variable=0
Some_function(Variable)
print (Variable)
I want the output to be 1 (or anything else but 0)
I tried using global by defining some_function like this, but it gave me an error "name 'Variable' is parameter and global"
def Some_function(Variable):
x=Variable+1
global Variable
Variable=x
You are using Variable as your global variable and as function parameter.
Try:
def Some_function(Var):
x=Var+1
global Variable
Variable=x
Variable=0
Some_function(Variable)
print (Variable)
You should not use the same name for parameter and the globale variable
The error message seem clear enough. Also, you wouldn't need to pass Variable as a parameter if you are using a global.
If you define
def f():
global x
x += 1
Then the following script should not output an error :
x = 1 # global
f(x)
print(x) # outputs 2
Another possibility :
def f(y):
return y+1
Which you can use like this :
x = 1
x = f(x)
print(x) # 2
If you want to modify global variable, you should not use that name as function parameter.
var = 0
def some_func():
global var
var += 1
some_func()
print(var)
Just use global keyword and modify variable you like.
Variable = 0
def some_function(Variable):
global x
x = Variable + 1
some_function(Variable)
Variable = x
print(Variable)

Im getting the referenced before assignment error

I am making a system that reads a file, moves it to a new file, and moves it back with a new variable at the end of each line.
It is saying that linesRead is referenced before assignment
import random
handVar = 0
handList = []
linesRead = 'test'
def dealCards(numPlayers, cardList):
random.shuffle(cardList)
for i in range(0, numPlayers):
poppedCard1=cardList.pop()
poppedCard2=cardList.pop()
hand = (poppedCard1 + ', ' + poppedCard2)
handList.append(hand)
cardFile = open('players.txt', 'r')
playerLines= cardFile.readlines()
cardFile.close()
for i in playerLines:
for f in i:
linesRead = linesRead + f
print(linesRead)
tempFile = open('tempFile.txt', 'w')
tempFile.write(playerLines)
tempFile.close
tempFile = open('tempFile.txt', 'r')
playerFile = open('players.txt', 'a')
for i in tempFile:
newLine= (i + ', ' + handList[handVar] + ', ' + handList[handVar+1])
playerFile.write(newLine)
handVar = handVar + 2
The reason for the error scopes of the variables.
You are defining the variable linesRead in the global scope (outside of the function). It is available inside the function as long as you do not try to reassign the variable. When you reassign, Python treats is as a local scope variable (the scope of the function), and since you are using it in the reassignment, it is not able to find the assignment of that var in local scope.
Let's look at the following examples:
num = 42
def foo():
print(num)
foo()
Output:
42
In this case num is a variable defined in the Global scope (aka. module scope). It is defined at the top level of the module and is available in the local scopes of functions.
But the things are different in the following example:
num = 42
def foo():
print(num)
num = 12
foo()
Output:
UnboundLocalError: local variable 'num' referenced before assignment
What happens in this case is Python making the num a variable of the local scope of the foo function. That is it has nothing to do with the num of the global scope. Since I'm trying to print it before I assign it a value, it gives me an error.
Things are different when I move the assignment above of the print function call:
num = 42
def foo():
num = 12
print(num)
foo()
Output:
12
Same happens in this case, but since num is already assigned in the local scope by the time I'm calling the print, it won't error.
Solution
One of the solutions is to include the var as a global in the function. Something like this
def dealCards(numPlayers, cardList):
global linesRead
it will make the var from global variable available at the local scope.
But in this case if you modify the var in the function, the one at the module level will be changed as well
num = 42
def foo():
global num
print(num)
num = 12
foo()
print(num)
Output
42
12
Here is a fine, detailed read on Python scopes:
https://realpython.com/python-scope-legb-rule/

Why is global keyword not ignored even if it is unreachable? (Python)

I am really new to programming and Python, so please really forgive me for my ignorance.
I just learned that using global can make a variable inside function be a global one.
However, I discovered something not with my expectation:
I tried the following code in Python 3.8 (forgive me for my ignorance as I don't know what else information I should provide):
>>> x = 0
>>>
>>> def function():
... if False:
... global x
... x = 1
...
>>> function()
>>> print(x)
and the result is 1.
However, I expected the code to have the same effect as the following code:
>>> x = 0
>>>
>>> def function():
... x = 1
...
>>> function()
>>> print(x)
which the result should be 0.
In my mind, the statement inside if False should not be executed, so it sounds strange to me.
Also, personally, I think that in some situation I would expect the variable inside a function, whether local or global, to be dependent on other codes... what I mean is, I would like to change if False to something like if A == 'A', while (I hope) I can control whether the x is global/local according to my conditional statement.
I tried to change if to while, but it's the same... there isn't a infinite loop, but the code global x is still executed/compiled...
I admit that it may sounds naive, and perhaps it just won't work in Python, but I really wonder why... It seems that the code global x is unreachable, but how come it is not ignored?
Can anyone please tell me about the reason? I would like to know more about the mechanism behind compilation(?)
Any help would be appreciated, thank you!
In python the global statement (and the nonlocal statement) are very different from the normal python code. Essentially no matter where a global statement in a function is, it influences always the current codeblock, and is never "executed". You should think more of it as a compiler directive instead of a command.
Note that the statement itself must come before any usage of the variable it modifies, i.e.
print(x)
global x
is a syntax error. The global statement can only modify variable behavior in the whole codeblock, you can't first have a non-global variable that later gets global and you can also not have conditional global variable
(I couldn't really find good documentation for this behavior, here it says "The global statement is a declaration which holds for the entire current code block." and "global is a directive to the parser. It applies only to code parsed at the same time as the global statement." but that doesn't seem super clear to me.)
There are more compiler directives in python, although they don't always look like one. One is the from __future__ import statements which look like module imports but change python behavior.
Global is not in execution path but in a scope. The scope is whole function. Statements like if for don't make scopes. If you use any assignment you create local variable. The same with global or nonlocal you bind symbol to variable from outside.
As Stanislas Morbieu typed, see doc.
Programmer’s note: global is a directive to the parser. It applies only to code parsed at the same time as the global statement.
Not at execution time.
x = 1
def fun():
y = x + 1
print(f'local x = {x}, y = {y}')
fun()
print(f'global x = {x}')
# Output:
# local x = 1, y = 2
# global x = 1
In example above, y uses global x (and adds 1).
x = 1
def fun():
y = x
x = y + 1
print(f'local x = {x}')
fun()
print(f'global x = {x}')
# Output:
# UnboundLocalError: local variable 'x' referenced before assignment
Look at last example. It doesn't assign y from global x because assignment in second line creates local x and y can not read local x before x assignment. The same with:
x = 1
def fun():
if False:
x += 1
fun()
# Output
# UnboundLocalError: local variable 'x' referenced before assignment
x assignment creates local variable.
If you want to change global variable under condition you can use globals().
x = 1
def set_x(do_set, value):
if do_set:
globals()['x'] = value
print(f'global x = {x} (init)')
set_x(False, 2)
print(f'global x = {x} (false)')
set_x(True, 3)
print(f'global x = {x} (true)')
# Output
# global x = 1 (init)
# global x = 1 (false)
# global x = 3 (true)
Proxy
I you want to decide with variable you want to use later (in the same scope) you need some kind of proxy IMO.
x = 1
def fun(use_global):
x = 2 # local
scope = globals() if use_global else locals()
scope['x'] += 1
print(f'local ({use_global}): x = {scope["x"]}')
print(f'global: x = {x} (init)')
fun(False)
print(f'global: x = {x} (false)')
fun(True)
print(f'global: x = {x} (true)')
# Output:
# global: x = 1 (init)
# local (False): x = 3
# global: x = 1 (false)
# local (True): x = 2
# global: x = 2 (true)
Maybe you can think about refactoring of your code if you need it.
If you can change local variable name (if not use globals() as above), you can proxy:
use dict (like in example above)
use list (x=[1]) and usage x[0]
use object (with builtin dict), example:
class X:
def __init__(self, x):
self.x = x
x = X(1)
def fun(use_global):
global x
my_x = x if use_global else X(2)
my_x.x += 1
print(f'local ({use_global}): x = {my_x.x}')
print(f'global: x = {x.x} (init)')
fun(False)
print(f'global: x = {x.x} (false)')
fun(True)
print(f'global: x = {x.x} (true)')
# Output:
# global: x = 1 (init)
# local (False): x = 3
# global: x = 1 (false)
# local (True): x = 2
# global: x = 2 (true)
Note. Variables in Python are only references. It is way you can not change x = 1 without global (or globals()). You change reference to local value 1.
But you can change z[0] or z['x'] or z.x. Because z referents to list or dict or object and you modify it content.
See: https://realpython.com/python-variables/#object-references
You can check real object by id() function, ex. print(id(x), id(my_x)).
As per the Python documentation, global is a directive to the parser so it is taken into account before the execution, therefore it does not matter if the code is reachable or not. The variable is global for the entire scope, which is the function in your case.

function inside a function - global and nonlocal scope

I'm trying out the following code with global, and nonlocal scope. following snippet working wihtout any issues.
def countdown(start):
n = start
def display():
print('--> %d' % n)
def decrement():
nonlocal n ##using python3
n -= 1
while n > 0:
display()
decrement()
countdown(10)
countdown(10)
but why can't i use the global n ? instead of nonlocal n. that gives me
UnboundLocalError: local variable 'n' referenced before assignment
this is the snippet
def countdown(start):
global n ##defined it global
n = start
def display():
print('--> %d' % n)
def decrement():
##no nonlocal varibale here
n -= 1
while n > 0:
display()
decrement()
countdown(10)
The global declaration doesn't automatically apply to nested functions. You need another declaration:
def decrement():
global n
n -= 1
so n in decrement also refers to the global variable.
You need to mark a variable as global in every function where you use it (or rather, every one where you assign to it). You marked n as global in countdown, but decrement still thinks it is local. If you want decrement to also use the global n, you need to put another global n inside decrement.

Python global/local variables

Why does this code work:
var = 0
def func(num):
print num
var = 1
if num != 0:
func(num-1)
func(10)
but this one gives a "local variable 'var' referenced before assignment" error:
var = 0
def func(num):
print num
var = var
if num != 0:
func(num-1)
func(10)
Because in the first code, you have created a local variable var and used its value, whereas in the 2nd code, you are using the local variable var, without defining it.
So, if you want to make your 2nd function work, you need to declare : -
global var
in the function before using var.
def func(num):
print num
var = 1 <-- # You create a local variable
if num != 0:
func(num-1)
Whereas in this code:
def func(num):
print num
var = var <--- # You are using the local variable on RHS without defining it
if num != 0:
func(num-1)
UPDATE: -
However, as per #Tim's comment, you should not use a global variable inside your functions. Rather deifine your variable before using it, to use it in local scope. Generally, you should try to limit the scope of your variables to local, and even in local namespace limit the scope of local variables, because that way your code will be easier to understand.
The more you increase the scope of your variables, the more are the chances of getting it used by the outside source, where it is not needed to be used.
If you have var = ... anywhere in a function, the name "var" will be treated as a local variable for the entire function, regardless of where that assignment occurs. This means that all occurrences of var in your function will be resolved in the local scope, so the right hand side of var = var results in the referenced before assignment error because var has not yet been initialized in the function's scope.
You can read a global without declaring it global. But to write a global, you need to declare it global.
In your second piece of code you have created a local variable in RHS and without defining it, you are assigning it to the LHS variable var which is global (a variable defined outside the function is considered global explicitly).
If your intention is to create a local variable inside the function and assign it to the value of the global variable, this will do the trick:
var = 0
def func(num):
print num
func.var = var # func.var is referring the local
# variable var inside the function func
if num != 0:
func(num-1)
func(10)
def runscan(self):
p = os.popen('LD_PRELOAD=/usr/libv4l/v4l1compat.so zbarcam
/dev/video0','r')
def input(self):
self.entryc.insert(END, code)
how about this?
i want use local 'code' to the next function to insert the result of barcode to my Tkinter entryBox..
Thanks
Each function block is a local scope. If you want to assign to global variables, you need to do so explicitly:
var = 0
def func(num):
print num
global var
var = 1
if num != 0:
func(num-1)
print var # 0
func(2)
print var # 1

Categories