Difference between local variable and global variable - python

I'm confused on the difference between local variables and global variables. I know that global variables are declared outside a function while local is declared in a function. However, I'm wondering if it is as so:
def func(l):
a = 0
n = len(l)
w = l[0]
while...
My question is, in the function i wrote as an example, i know that a is a local variable but what about the other two? are they local variables too?

l is a location variable that you passed into the function, and so is w since w is a "copy" of l[0]
To have a global variable you need to declare the variable as global using the global keyword.
x = 1
y = 2
def func(l):
global x
x = 4
l = 5
print("x is {0}, y is {1}".format(x,l))
func(y)
print("x is {0}, y is {1}".format(x,y))
Returns:
x is 4, y is 5
x is 4, y is 2
Notice how x is now changed but y isn't?
Note that lists are special because you don't need to declare the global keyword to append or remove from them:
x = []
def func():
x.append(3)
print("x is {0}".format(x))
func()
print("x is {0}".format(x))
Returns:
x is [3]
x is [3]
But references to lists are not global because they are a 'copy' of it :
x = [3]
y = 1
def func():
y = x[0]
print("y is {0}".format(y))
func()
print("y is {0}".format(y))
Returns:
y is 3
y is 1
Also Reassigning the variable that was a list is not global:
x = [3]
def func():
x = [2]
print("x is {0}".format(x))
func()
print("x is {0}".format(x))
Returns:
x is [2]
x is [3]
Also note that there are always a better way to do something than to declare global variables, because as your code scales it will get messier.

All those variables are assigned values and that automatically declares them in the local scope. So they are local variables.
Even if they had been declared outside in the global scope, they would still be local.
Unless you used the global keyword which tells the interpreter that the current scope refers to a previously declared global or creates a new one in the global context if none with the same name exists.
def func(l):
global n # n is declared in the global scope
a = 0
n = len(l)
w = l[0]
while...
func()
print(n)

All the variables in your function are local, usable by that function only. Global variables are usable by all functions in the class. In your function
def func(l):
a = 0
n = len(l)
w = l[0]
while...
>>>a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
a, n, w, and l are not usable outside of the func scope. If you did something like this...
a = 0
def func(l):
n = len(l)
w = l[0]
while...
>>>a
0
I just happened to come across this read which provides you with a lot of detail on variable declaration and scope.

[Python Doc the rule for local and global variables]:
In Python, variables that are only referenced inside a function are
implicitly global. If a variable is assigned a value anywhere within
the function’s body, it’s assumed to be a local unless explicitly
declared as global. illustrate this with your example:
Use your example to illustrate, all variables declared inside the func are local variables. and even values declared outside of the function. like variable x it has no parent function but it is still actually NOT a global variable. x just get commits to memory before the func gets called
x = 5 #actually local
def func(l):
a = 0
n = len(l)
w = l[0]
print(x) # x is local we call call it, use it to iterate but thats is pretty much it
if we try to modify the local variable x you would get an error:
x = 5
def func(l):
a = 0
n = len(l)
w = l[0]
x = x + 1 # can't do this because we are referning a variable before the funtion scope. and `x` is not global
UnboundLocalError: local variable 'x' referenced before assignment
but now if we define x as global then we can freely modify it as Python know anywhere when we call x is references to the same variable and thus the same memory address
x = 5
def func():
global x
x = x + 1
func()
print(x)
it prints out : 6 for the value of x
Hope through this example you see that global variable can be accessed anywhere in the program. Whereas local variable can only be accessed within its function scope. Also, remember that even though global variables can be accessed locally, it cannot be modified locally inherently.

Local Variable : When we declare a variable inside a function, it becomes a local variable.
global variable : When we declare a variable outside a function , it becomes a global variable.
A python program understand difference local vs global variable
#same name for local and global variable.
a = 1 #this is global variable
def my_function():
a = 2 #this is local variable
print("a= ", a) #display local var
my_function()
print("a = ", a) #display global var.
This program to access global variable
a = 1 #This is global var
def my_function():
global a #This is global var.
print("global a= ", a) #display new value
a = 2 #modify global var value
print("modify a = ", a) #display a new value
my_function()
print("global a= ", a) #display modified value

Related

Closure and variable scope in python 3.x issue causing me confusion

I am using Python 3.7.0 and I am doing some experiments in order to comprehend the subtleties of variable scopes but I still don't understand this behaviour.
When I execute this code:
def f():
x=0
def g():y=x+1;x=y
return g
f()()
I get UnboundLocalError: local variable 'x' referenced before assignment
However when I execute this one:
def f():
x=0
def g():y=x+1
return g
f()()
It works fine. And even this one:
def f():
x=0
def g():x=1
return g
f()()
It also works fine. So I am confused. It seems to me that if assigning the value 1 to the nonlocal variable x in the g function works fine alone and on the other hand if assigning an expression containing x to a local variable y in the function g works also fine then the instructions y=x+1 and x=y should both work. I don't understand what is causing the error. I feel I am missing something fundamental in my understanding of Python's behaviour.
I'll take an ill-advised crack at this. In the following code:
def f():
x = 0 # assignment makes this x local to f()
def g():
y = x + 1
x = y # assignment makes this x local to g()
return g
f()()
The assignment of x inside g() forces it to be a variable local to g(). So the first line causes the error as you accessing the value of an unassigned local. I believe this "assignment makes it local" logic doesn't follow the flow of your program -- the function is viewed as whole to make this determination and then the code is looked at line by line.
You can access any variable in scope from a function, but you can only set locals. Unless you've declared the variable you're assigning as global or nonlocal:
def f():
x = 0 # assignment makes this x local to f()
def g():
nonlocal x
y = x + 1
x = y # x is declared to come from a nonlocal scope
return g
f()()
In your second example, it's not an issue as you're only looking at the value of x, not setting it, so it can come from any appropriate scope:
def f():
x = 0 # assignment makes this x local to f()
def g():
y = x + 1 # x comes from an outer scope
return g
f()()
Finally, your third example is the same as the first without the unssigned local variable usage error:
def f():
x = 0 # assignment makes this x local to f()
def g():
x = 1 # assignment makes this x local to g()
return g
f()()
It seems to me that if assigning the value 1 to the nonlocal variable
x in the g function works fine alone
How did you determine that the reassignment of x in f() worked fine?

Any type of scope resolution operator in Python?

Is there any way to make the python interpreter choose the global variable specifically when there is also a local variable with the same name? (Like C++ has :: operator)
x=50
def fun():
x=20
print("The value of local x is",x)
global x
#How can I display the value of global x here?
print("The value of global x is",x)
print("The value of global x is",x)
fun()
The second print statement inside the function block should display the value of global x.
File "/home/karthik/PycharmProjects/helloworld/scope.py", line 7
global x
^
SyntaxError: name 'x' is used prior to global declaration
Process finished with exit code 1
Python does not have a direct equivalent to the :: operator (typically that kind of thing is handled by the dot .). To access a variable from an outer scope, assign it to a different name as to not shadow it:
x = 50
def fun():
x = 20
print(x) # 20
print(x_) # 50
print(x) # 50
x_ = x
fun()
But of course Python would not be Python if there weren't a hack around this... What you describe is actually possible, but I do not recommend it:
x = 50
def fun():
x = 20
print(x) # 20
print(globals()['x']) # 50
print(x) # 50
fun()
I don't know any way to do this (and I am not an expert). The two solutions that I can think of are to give another name to your local x (like xLoc), or to put your global x in argument, like this :
x=50
def fun(xGlob):
x=20
print("The value of local x is",x)
print("The value of global x is",xGlob)
print("The value of global x is",x)
fun(x)
Is this answering your question ?

Scoping rules in python

Consider the following python snippet (I am running Python 3)
name = "Sammy"
def greet():
name = 'johny'
def hello():
print('hello ' + name) # gets 'name' from the enclosing 'greet'
hello()
greet()
This produces the output hello johny as expected
However,
x = 50
def func1():
x = 20
def func2():
print("x is ", x) # Generates error here
x = 2
print("Changed the local x to ",x)
func2()
func1()
print("x is still ",x)
generates an UnboundLocalError: local variable 'x' referenced before assignment.
Why does the first snippet work, whereas the second doesn't?
The error is actually caused (indirectly) by the following line, i.e. x = 2. Try commenting out that line and you'll see that the function works.
The fact that there is an assignment to a variable named x makes x local to the function at compile time, however, at execution time the first reference to x fails because, at the time that the print() statement is executed, it does not exist yet in the current scope.
Correct it by using nonlocal in func2():
def func2():
nonlocal x
print("x is ", x)
x = 2
print("Changed the local x to ",x)
The reason that the first function (greet()) works is because it's OK to read variables in an outer scope, however, you can not assign to them unless you specify that the variable exists in an outer scope (with nonlocal or global).
You can assign to a variable of the same name, however, that would create a new local variable, not the variable in the outer scope. So this also works:
def func1():
x = 20
def func2():
x = 2
print('Inner x is', x)
func2()
print('Outer x is', x)
Here x is assigned to before being referenced. This creates a new variable named x in the scope of function func2() which shadows the x defined in func1().
In a given scope, you can only reference a variable's name from one given scope. Your variable cannot be global at some point and local later on or vice versa.
For that reason, if x is ever to be declared in a scope, Python will assume that you are refering to the local variable everywhere in that scope, unless you explicitly state otherwise.
This is why you first function, greet, works. The variable name is unambiguously coming from the closure. Although, in func2 the variable x is used in the scope and thus you cannot reference the x from the closure unless explicitly stating otherwise with nonlocal.
The following errors might enlighten us on this.
A variable cannot become global after use
def func1():
x = 20
def func2():
print("x is ", x)
global x
print("Changed the local x to ",x)
func2()
This raises a SyntaxError: name 'x' is used prior to global declaration. This means that the closure's x cannot be used and then the global one.
A global variable cannot become local
Here is another case using global at the top of func2.
def func1():
x = 20
def func2():
global x
print("x is ", x)
x = 2
print("Changed the local x to ",x)
func2()
This code was exectued without error, but notice that the assignment to x updated the global variable, it did not make x become local again.

Python's closure - local variable referenced before assignment

I am trying to understand how closure works in Python.
I feel like add1 should work just fine here. I would expect the variable x to have been defined when helper is called. However, it is giving me a Local variable referenced before assignment error.
add2 is very similar to add1. Instead of assigning x with an integer, it assigns it with a dictionary. The behavior of it is also aligned with what I would expect. x is defined and reference-able inside helper.
import random
def add1():
x = 0
def helper():
x = x + 1
return x
return helper
def add2():
x = {}
def helper():
x[random.randint(1,1000)] = 3
return x
return helper
if __name__ == '__main__':
a1 = add1()
a2 = add2()
# print(a1()) #This causes error
print(a2()) #{650: 3}
print(a2()) #{650: 3, 333: 3}
What's the logic behind this? What am I doing differently other than that the types of x are different?
You're expecting the compiler to know that the variable has been bound outside the closure. This is not true, and hence you need to use nonlocal to indicate this.
def add1():
x = 0
def helper():
nonlocal x
x = x + 1
return x
return helper
EDIT By denniss:
nonlocal is not necessary in add2 because it's just modifying x and not re-binding it (aka not re-assigning it). Whereas in add1, x= x+1 is a re-assignment.

Why can't I set a global variable in Python?

How do global variables work in Python? I know global variables are evil, I'm just experimenting.
This does not work in python:
G = None
def foo():
if G is None:
G = 1
foo()
I get an error:
UnboundLocalError: local variable 'G' referenced before assignment
What am I doing wrong?
You need the global statement:
def foo():
global G
if G is None:
G = 1
In Python, variables that you assign to become local variables by default. You need to use global to declare them as global variables. On the other hand, variables that you refer to but do not assign to do not automatically become local variables. These variables refer to the closest variable in an enclosing scope.
Python 3.x introduces the nonlocal statement which is analogous to global, but binds the variable to its nearest enclosing scope. For example:
def foo():
x = 5
def bar():
nonlocal x
x = x * 2
bar()
return x
This function returns 10 when called.
You need to declare G as global, but as for why: whenever you refer to a variable inside a function, if you set the variable anywhere in that function, Python assumes that it's a local variable. So if a local variable by that name doesn't exist at that point in the code, you'll get the UnboundLocalError. If you actually meant to refer to a global variable, as in your question, you need the global keyword to tell Python that's what you meant.
If you don't assign to the variable anywhere in the function, but only access its value, Python will use the global variable by that name if one exists. So you could do:
G = None
def foo():
if G is None:
print G
foo()
This code prints None and does not throw the UnboundLocalError.
You still have to declare G as global, from within that function:
G = None
def foo():
global G
if G is None:
G = 1
foo()
print G
which simply outputs
1
Define G as global in the function like this:
#!/usr/bin/python
G = None;
def foo():
global G
if G is None:
G = 1;
print G;
foo();
The above python prints 1.
Using global variables like this is bad practice because: http://c2.com/cgi/wiki?GlobalVariablesAreBad

Categories

Resources