How is my function not inheriting from global variable[python]? [duplicate] - python

This question already has answers here:
Using global variables in a function
(25 answers)
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 5 years ago.
Why is this code giving 'UnboundLocalError: local variable 'num1' referenced before assignment' error?
num1=50
def func():
print(num1)
num1=100
func()

Another gotcha! of python. This is because of hoisting and variable shadowing. If you have a local and global variable with the same name in a particular scope, the local variable will shadow the global one. Furthermore, declarations are hoisted to the top of their scope.
So your original code will look something like this:
num1=50
def func():
num1 = ... # no value assigned
print(num1)
num1=100
func()
Now, if you try to print num1 without having assigned any value to it, it throws UnboundLocalError since you have not bound any value to the variable at the time you are trying to dereference it.
To fix this, you need to add the global keyword to signify that num1 is a global variable and not local.
num1=50
def func():
global num1
print(num1)
num1=100
func()

Related

Difference between global/local variables in Python [duplicate]

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 4 months ago.
test=4
def sum1(var):
print("in function, test",test)
var+=1
test=7
print("in function, var",var)
print("in function, test",test)
sum1(5)
print(test)
I'm trying to understand global and local variable, so I try it this way: a global and a local variable that has same names (I know we normally don't do that).
In this program it has an "UnboundLocalError: local variable 'test' referenced before assignment"
I am wondering why the first print() that prints the test cannot be printed out? Why wouldn't it call the global "test"?
Because your local test shadows the name of the global test, it's unclear to which one you're referring. If you comment out the line test = 7 in your function, you won't get the error, as python assumes you're referring to the global test.
If you insist on using var names in your local scope that shadow global vars (and you've just discovered why that's a very bad idea), you can be explicit about it:
def sum1(var):
global test
print("in function, test", test)
...
Now, however, when you get to test = 7, you're modifying the global test var. That's probably not what you wanted.

Variable scope with dictionaries [duplicate]

This question already has answers here:
Global dictionaries don't need keyword global to modify them? [duplicate]
(2 answers)
Closed 2 years ago.
This executes without error:
def myfunction():
global a_dict
a_dict['s'] = 'whatevs'
b_dict['s'] = 'lalala'
a_dict = b_dict
a_dict = {'s':[], 'm':[]}
b_dict = {'s':[], 'm':[]}
myfunction()
Why does this not throw an error without also adding global b_dict to the function - as I'm writing to both dictionaries?
It sure does if I comment out the global a_dict ("'a_dict' referenced before assignment") - as I would expect.
You only need global foo when you want to assign to the global name foo. You are not assigning to b_dict; you are assigning to one of its keys, equivalent to b_dict.__setitem__('s', 'lalala'). Both uses of b_dict treat it as a free variable, since there is no local variable named b_dict defined.
The value of a free variable is taken from the closest enclosing scope (in this case, the global scope) where it is defined.
The fact of declaring a variable as global in a function allows you to use a variable outside that function. If there is no variable b declared inside it, Python is going to assume it is a global variable declared before the function call.

Why does python behave this way with variables? [duplicate]

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 months ago.
I have been trying to understand why python behaves this way, in the block of code below. I have done my research but couldn't find a good answer so I came here to see if anyone can point me in the right direction or provide a good clarification.
I understand that it has to do with some old ALGOL principle, but I don't fully understand it.
var = 5
def func1():
print(var)
func1()
def func2():
var = 8
print(var)
func2()
def func3():
print(var)
var = 8
func3()
The output of this code is as follows:
5
8
UnboundLocalError: local variable 'var' referenced before assignment
I understand why we get the outputs '5' and '8'. But with 'func3()', I was expecting an output of '5'. As it seems, the interpreter thinks that I want to print the local 'var' in the function instead of the global 'var'. So it throws this error.
Or maybe if a variable is defined somewhere inside of the function, then the function will default to the local variable, instead of a global one with the same name.
But why exactly does python behave this way ? I am not complaining, I am just trying to understand something...
How could I use a predefined global variable in a function, then define a local variable with the same name inside of the same function, without changing the value of the global variable ? ( in python of course )
Thanks in advance to everyone here. You are amazing people ! :)
Edit_1: Thanks every one for the great answers. I totally understand that it is a bad and unpractical idea to use a predefined global variable in a function, then define a local variable with the same name inside of the same function. I was just thinking about it from a theoretical perspective, because I saw it in a college lecture. XD
I can't find a single use case, in which it would be optimal to do that either !
Edit_2: I already read the PEP8 and I know that being explicit is better than being implicit. :)
It's true. Otherwise the code will be confusing and lead to bugs.
That question was just about some useless and impractical college theory that I was trying to understand.
Edit_3:
Now I fully understand why it happens and what is going on here. Thanks to Randall Valenciano for providing this link to a blog that explains it very well.
What happens is that the function is interpreted as a whole, and not line by line. So when the function is being interpreted, the variable declarations of any defined variables, are moved to the top of the function. So when we are printing 'var', the function is using the locally declared variable that doesn't have any value assigned to it yet, and then the interpreter complains about it and throws and error.
Thanks to all of you again ! :)
You have been of great help to me ! Now I finally understand what is going on there under the hood.
Your var is defined as a global variable. In each function when you're only reading the var you're accessing the global var, but the moment there's an assigned value to var somewhere in the function, python treats every var within the function as a local variable. Thus why your last function failed, because print(var) (the local varaible) was called before var = 8 was assigned.
You can read up a bit about more in these threads:
How bad is shadowing names defined in outer scopes?
Python nonlocal statement
The best thing to do is be explicit about your code so it's no longer confusing if you're trying to reference a local, nonlocal or global variable.
In this case, assuming your intention is to keep using the global var, do this:
var = 5
def func1():
print(var)
func1()
def func2():
global var
var = 8
print(var)
func2()
def func3():
global var
print(var)
var = 8 # technically this is not necessary any more var = 8 was already assigned when func2() is called
func3()
The output is thus:
5
8
8
Edit: Thanks to juanpa.arrivillaga's comment - I missed your original question.
How could I use a predefined global variable in a function, then
define a local variable with the same name inside of the same
function, without changing the value of the global variable ? ( in
python of course )
The short answer is - define the local var first like you did in func2() and you're good. The longer answer though is - why would you want to do that? It creates confusion and becomes a headache to track which is when you have variables of the same name in different scope. A better approach would be name your local var to be local_var or something so it's distinctly different and easily traced.
Here's a rule for Python Scope Resolution from this answer
LEGB Rule.
L, Local — Names assigned in any way within a function (def or lambda)), and not declared global in that function.
E, Enclosing-function locals — Name in the local scope of any and all statically enclosing functions (def or lambda), from inner to outer.
G, Global (module) — Names assigned at the top-level of a module file, or by executing a global statement in a def within the file.
B, Built-in (Python) — Names preassigned in the built-in names module : open,range,SyntaxError,...
So basically in your question, the scope resolution is "from inside out" and since you aren't using the global keyword, the interpreter doesn't know to look outside the local function scope to find that variable var. All the interpreter sees is that you are using a variable before declaring and defining it, thus throwing the error. Global variables are often dangerous, and so Python wants to make sure you know you want to use a global variable by forcing you to be explicit about it.
See this other answer for an explanation of the global keyword
Hope it helps.

globals() scope inside a function [duplicate]

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Using global variables in a function
(25 answers)
Closed 5 years ago.
I have a question regarding globals() in python
My sample code
b=9
def a1():
'kkk'
a1()
print globals()
I got output b as global
Since b is global, I am expecting I can modify it anywhere
So I modified my code to
b=9
def a1():
'kkk'
b=100
a1()
print globals()
still my globals() says b as 100. Why b inside the function is taken as local value while my globals() says its global?
Note: If I add keyword global b inside the function, it get convert to global.
My question is why b was not getting modified inside the function while globals() declare b as global ?
Refer Python docs for more information. Copying the text in case URL doesn't work
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.
Though a bit surprising at first, a moment’s consideration explains this. On one hand, requiring global for assigned variables provides a bar against unintended side-effects. On the other hand, if global was required for all global references, you’d be using global all the time. You’d have to declare as global every reference to a built-in function or to a component of an imported module. This clutter would defeat the usefulness of the global declaration for identifying side-effects.
inside a function, unless you use the keyword global, it is not global variable that is modified. instead,a local variable is created and is destroyed as soon as it is out of scope
As your code b is a local variable in a1(), to use global variable, you should first say that to python and then use it, as follows:
b=9
def a1():
'kkk'
global b
b=100
a1()
print globals()

UnboundLocalError: local variable 'url_request' referenced before assignment [duplicate]

This question already has answers here:
Using global variables in a function
(25 answers)
Closed 8 years ago.
Think I'm going nuts here.
url_request = 0
def somefunction():
url_request+=1
if __name__ =='__main__':
somefunction()
Gives me the UnboundLocalError. What important concept am I missing here?
You are assigning to a global variable, which means you need to mark it as a global:
def somefunction():
global url_request
url_request+=1
When you assign to a variable in a local scope, it is assumed to be a local variable unless you use a global statement to tell python otherwise first.
For Python 2.7 we have to types of variables: global, local. Each function create it's own local scope for variables.
From local scope you can read without any restrictions. You can also call global object methods, so you can modify variable from global. But you can't reassign value.
Look at this code:
requests = [1,2,3]
def modify():
requests.append(4)
def redeclare():
requests = [10,20,30]
modify()
print requests
# will give you [1,2,3,4]
redeclare()
print requests
# will give you [1,2,3,4]
What's going on? You can't reassign requests variable from local scope, so interpreter create for you other variable - in local scope for redeclare call context.
Regarding to your code... Firstly, you try to reassign variable from global scope. Why? url_request is int, int is immutable, so operation url_request+=1 doesn't change value, it should reassign new value to variable name. Secondly, you don't specify global identify for this variable. So only one option for interpreter - to assume url_request as local variable. But... You didn't declare it's value anywhere....
UnboundLocalError means that you try to perform operations with variable value without declaring it before. Hope this will help you to understand more about Python variables/names/scopes.

Categories

Resources