This question already has answers here:
Using global variables in a function
(25 answers)
Closed 6 months ago.
This is saved in my file function_local.py:
x = 50
def func(x):
print('x is', x)
x = 2
print('Changed local x to', x)
func(x)
print('x is still', x)
Output:
$ python function_local.py
x is 50
Changed local x to 2
x is still 50
Question: When we print the first line inside the Function, why does it print out 50, not 2? Even if it is said, in the function, that x = 2?
In case you assign to a variable name (that wasn't declared global or nonlocal) in a function or use the variable name in the argument list of the function the variable name will become part of the function.
In that case you could've used any variable name inside the function because it will always refer to the local variable that was passed in:
x = 50
def func(another_x):
print('local x =', another_x)
another_x = 2
print('local x =', another_x)
return another_x
print('global x =', x)
x = func(x) # note that I assigned the returned value to "x" to make the change visible outside
print('global x =', x)
More explanation
I'm going to try to show what I meant earlier when I said that x with "will become part of the function".
The __code__.co_varnames of a function holds the list of local variable names of the function. So let's see what happens in a few cases:
If it's part of the signature:
def func(x): # the name "x" is part of the argument list
pass
print(func.__code__.co_varnames)
# ('x',)
If you assign to the variable (anywhere in the function):
def func():
x = 2 # assignment to name "x" inside the function
print(func.__code__.co_varnames)
# ('x',)
If you only access the variable name:
def func():
print(x)
print(func.__code__.co_varnames)
# ()
In this case it will actually look up the variable name in the outer scopes because the variable name x isn't part of the functions varnames!
I can understand how this could confuse you because just by adding a x=<whatever> anywhere in the function will make it part of the function:
def func():
print(x) # access
x = 2 # assignment
print(func.__code__.co_varnames)
# ('x',)
In that case it won't look up the variable x from the outer scope because it's part of the function now and you'll get a tell-tale Exception (because even though x is part of the function it isn't assigned to yet):
>>> func()
UnboundLocalError: local variable 'x' referenced before assignment
Obviously, it would work if you access it after assigning to it:
def func():
x = 2 # assignment
print(x) # access
Or if you pass it in when you call the function:
def func(x): # x will be passed in
print(x) # access
Another important point about local variable names is that you can't set variables from outer scopes, except when you tell Python to explicitly not make x part of the local variable names, for example with global or nonlocal:
def func():
global x # or "nonlocal x"
print(x)
x = 2
print(func.__code__.co_varnames)
# ()
This will actually overwrite what the global (or nonlocal) variable name x refers to when you call func()!
In your function
def func(x):
print('x is', x)
x = 2
print('Changed local x to', x)
x is not a global variable; it is a local variable due to the assignment on the second line of the body. If you are going to assign to a global variable, it must be explicitly declared as such:
def func(x):
global x
print('x is', x)
x = 2
print('Changed local x to', x)
(Note: I missed that x is actually a function parameter. See https://nedbatchelder.com/text/names.html for an explanation of assignments to local names do not affect global names.)
this could be easily understand by this.
x = 50
def func(x):
print "Local variables: "+str(locals())
print('x is', x)
x = 2
print "Local variables: "+str(locals())
print('Changed local x to', x)
func(x)
print('x is still', x)
and the output
Local variables: {'x': 50}
'x is', 50
Local variables: {'x': 2}
'Changed local x to', 2
'x is still', 50
however if you want to access the x from outer scope after defining the x in func there is a way, I am not sure if it would create a issue or not though.
def func(x):
x = 2
print "local x == %s" % x
print "global x == %s" % globals().get('x')
func(x)
print "x is still %s" % x
Following will be output of the run.
local x == 2
global x == 50
x is still 50
Related
This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 8 years ago.
I'm doing a homework assignment for my CompSci class and this question came up:
x = 6
def fun(x):
y = x**2
x = y
return(x)
fun(x)
When running this, the value that is printed out is 36, but when a run print(x), x is still 6.
I would like to know why this happens; why x does not change?
Thanks!
That's because 'global x' is different than 'fun x', 'fun x' overlaps/masks the 'global x', does whatever you do with it and then it ceases to exist. The mask is not there so former 'global x' is again the current 'x'.
As stated you can overcome this by using 'global x' inside the function, note the difference between fun1 and fun2
x = 10
print "'x' is ", x
def fun1(x):
print "'x' is local to fun1 and is", x
x = x**2
print "'x' is local to fun1 and is now", x
def fun2():
global x
print "'x' is global and is", x
x = x ** 2
print "'x' is global and is now", x
print "'x' is still", x
fun1(x)
print "'x' is not local to fun anymore and returns to it's original value: ", x
fun2()
print "'x' is not local to fun2 but since fun2 uses global 'x' value is now:", x
output:
'x' is 10
'x' is still 10
'x' is local to fun1 and is 10
'x' is local to fun1 and is now 100
'x' is not local to fun anymore and returns to it's original value: 10
'x' is global and is 10
'x' is global and is now 100
'x' is not local to fun2 but since fun2 uses global 'x' value is now: 100
x = 6
def fun(x):
y = x**2
x = y
return(x)
# Reassign the returned value since the scope changed.
x = fun(x)
OR
x = 6
def fun():
# generally bad practice here
global x
y = x**2
x = y
fun()
if you want to modify global variable in function use global keyword:
global x
otherwise local variable will be created during assignment.
I'm reading the python reference name resolution, which reads
A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace.
Based on that, I would expect the following code
x = 10
def f():
x = 5
class Test:
y = x
return Test
print(f().y)
to print 10, however it prints 5. is this a mistake in the reference, or am I misunderstanding something?
In this case, 'normal' rules apply:
x = 'global'
def f():
x = 'defined in f'
class Test:
print(x) # not local, normal rules apply
f()
# defined in f
In this second case, we would expect an UnboundLocalError: local variable 'x' referenced before assignment if we were inside a function:
x = 'global'
def f():
x = 'defined in f'
class Test:
print(x) # unbound local at this time
x = 'assigned in Test'
print(x)
But for the first print(x), x will be taken from the global namespace:
f()
# global
# assigned in Test
I think #khelwood gave the answer. The value in the variable:
Test.y
is an integer that you define, but you never give the x = 10 to the function.
Maybe what you want is actually:
x = 10
def f(x=5):
class Test:
y = x
return Test
print(f().y) #print default 5
print(f(x).y)
The last line print 10 since x is given to the function, and therefore the class set y as x
You can see the exception by wrapping f in another function that defines a local variable x:
x = 10
def g():
x = 7
def f():
class Test:
y = x
return Test
return f()
print(g().y)
Now the output is 7, as the lookup of x in the class statement bypasses the local scope of g to find the global value of x.
In your code, because class establishes a new namespace, but not a new scope, the value of x is taken from the current local scope, that of f.
This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 5 years ago.
x=100
def fun2():
print x
x=10000
print x
fun2()
The above program showing local variable x reference before assignment. Why it is not printing
100
10000
x in the function is a local variable and can't access the other local variable you define first because they are in different scope.
Add global x to the start of your function or define x inside the function.
You appear to not know about variable scoping.
The variable x does not exist in the function scope.
You have to place global x before your print statement in order to access the global variable x.
x = 1 # Global x
def f():
x = 2 # function-local x
print(x) # prints 2
f()
print(x) # prints 1 because it uses the global x which remains unchanged
If you want that to work you need to specify inside the function that the x variable you are using is the one in the global scope by using the global keyword.
x=100
def fun2():
# Add this line
global x
print x
x=10000
print x
fun2()
Below code will print the value of x -> 100, as it is there in main scope #samba, but when you change the value of it doesn't work that way as it is not defined in the function.
x = 100
def fun2():
print(x)
fun2()
This doesn't work as the same way:
x = 100
def fun2():
print(x)
x = 1000
print(x)
fun2()
and through error:
UnboundLocalError: local variable 'x' referenced before assignment
x is a local variable and not initialised in function fun2().
You need to understand variable scoping here, Please check Global and Local variable scope
If you want to use it globally use global keyword in your function.
Because u assigned variable before function.
Just try this
def fun2():
x=100
print x
x=10000
print x
fun2()
It will output 100 and 1000
This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 8 years ago.
I'm doing a homework assignment for my CompSci class and this question came up:
x = 6
def fun(x):
y = x**2
x = y
return(x)
fun(x)
When running this, the value that is printed out is 36, but when a run print(x), x is still 6.
I would like to know why this happens; why x does not change?
Thanks!
That's because 'global x' is different than 'fun x', 'fun x' overlaps/masks the 'global x', does whatever you do with it and then it ceases to exist. The mask is not there so former 'global x' is again the current 'x'.
As stated you can overcome this by using 'global x' inside the function, note the difference between fun1 and fun2
x = 10
print "'x' is ", x
def fun1(x):
print "'x' is local to fun1 and is", x
x = x**2
print "'x' is local to fun1 and is now", x
def fun2():
global x
print "'x' is global and is", x
x = x ** 2
print "'x' is global and is now", x
print "'x' is still", x
fun1(x)
print "'x' is not local to fun anymore and returns to it's original value: ", x
fun2()
print "'x' is not local to fun2 but since fun2 uses global 'x' value is now:", x
output:
'x' is 10
'x' is still 10
'x' is local to fun1 and is 10
'x' is local to fun1 and is now 100
'x' is not local to fun anymore and returns to it's original value: 10
'x' is global and is 10
'x' is global and is now 100
'x' is not local to fun2 but since fun2 uses global 'x' value is now: 100
x = 6
def fun(x):
y = x**2
x = y
return(x)
# Reassign the returned value since the scope changed.
x = fun(x)
OR
x = 6
def fun():
# generally bad practice here
global x
y = x**2
x = y
fun()
if you want to modify global variable in function use global keyword:
global x
otherwise local variable will be created during assignment.
It's so basic it should work. I want a function that adds a value to something
There must be something I don't know about python 3, so here we go.
x = 0
def foo(x=x): ##### with out x=x there is a error
x = x + 1 # option one
x = 1 # option two
# when we run it
foo()
print(x)
# it returns 0, it should return 1
x is a local variable in foo(); Assigning x as a default value for a keyword argument won't make it any less a local.
If you wanted it to be a global, mark it as such:
x = 0
def foo():
global x
x = x + 1
print(x)
foo()
print(x)
but you probably just wanted to pass in the value as an argument instead:
def foo(value):
return value + 1
x = 0
print(x)
x = foo(x)
print(x)
This is basically and example of scoping rules. The variable x within foo is local to foo, so nothing that happens to the local x changes anything outside foo, including the global x with which is actually a different variable. When the interpreter exits foo the global x comes back into scope and it hasn't changed from its initial value of 0. The function header foo(x=x) defines a local x whose default value is the global x. The interpreter allows it but it's generally considered bad programming practice to have the same variable name representing two variables because it leads to this kind of confusion.