Consider this code:
Var='global'
def func():
Var='local'
#global Var
print Var
I'm trying to print the global variable even though I have a local variable with the same name.
However, when I use the keyword global, it gives me an error.
Is there a way to do this?
I would also appreciate an explanation of why global gives an error.
Use globals() which is a built-in function. From documentation for globals():
Return a dictionary representing the current global symbol table. This is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called).
Var='global'
def func():
Var='local'
print(globals()['Var'])
Reply to your comment:
First try this:
Var='global'
def func():
Var='local'
global Var
Var = 'Global'
print(Var)
func()
print(Var)
Amazed? What's going on here is that Python assumes that any variable name that is assigned to, within a function, is local to that function unless explicitly told otherwise. If it is only reading from a name, and the name doesn't exist locally, it will try to look up the name in any containing scopes (e.g. the module's global scope). In your case there is a local variable Var with the same name as the global Var, so the global variable is shadowed. Since Var exists locally, it does not need to be looked up in any containing scopes, and thus the local variable is used. However, when you change the value of Var (using global Var statement) Python uses the global variable, which can be seen by printing global Var in the global scope. As a matter of fact, the global keyword is actually used to modify a global variable from any local sub-scope. See here. Hope it is clear!
P.S.: I gathered the knowledge from Jeff Shannon's answer.
Related
I have a code in which I declare a variable globally. Then inside a function, when I try to use it, it gives an error Unbound variable is not declared
My code:
count_url =1
def foo():
...
ttk.Label(canvas1, text=f'{varSongTitle}...Done! {count_url}/{str(var_len)}').pack(padx=3,pady=3)
root.update()
count_url = count_url + 1
When I read from here that for bypassing this issue: The issue as I guess was that inside function my globally declared variable was becoming local, I guess because after printing it out I was assigning it to count_url =+ That's why I needed to also decalre it globally inside function as below:
count_url =1
def foo():
global count_url
...
ttk.Label(canvas1, text=f'{varSongTitle}...Done! {count_url}/{str(var_len)}').pack(padx=3,pady=3)
root.update()
count_url = count_url + 1
Now code works perfectly! But I have pair of questions How? Why?. Why it does not behave similarly if I assign global in global scope like
global count_url
count_url=1
def foo():
...
And also How can this be possible, that due to assigning inside the function a value to my global variable, why it becomes local?
ANSWER: https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
This is because when you make an assignment to a variable in a scope, that variable becomes local to that scope and shadows any similarly named variable in the outer scope. Since the last statement in foo assigns a new value to x, the compiler recognizes it as a local variable. Consequently when the earlier print(x) attempts to print the uninitialized local variable and an error results.
The default behavior of Python is to create a new variable in the function scope without checking the global scope for a similarly named variable.
The global declaration inside the function tells Python that you want to use the variable declared in the outer scope instead of creating a new one.
Adding a reference to the official Python documentation, from a comment: https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
variable= 0
def func():
global variable #(or variable = None)
variable = 1
def display():
print(variable)
func()
display()
What is the difference between "global variable" or "variable = None" ?
I think the major difference is that declaring global will open it's scope to all the functions.
But declaring it as None will just initialize an uninitialized variable and creating a new local variable.
The default scope of a variable inside a function will be local. So, when you assign variable = None, you are creating a local variable and assigning none to it. Whereas, if you declare it as global, you'll be modifying the global variable that you initialized earlier.
In python, any global variables initialized outside a function is accessible inside a function. However this access is automatic only if you are using it as a read only variable.
If you assign to the same name inside a function, a new variable of local scope is created. The global keyword tells python that you don't want a local instance, but would like to modify the global variable outside.
So in your example func() modifies the global variable and the same variable is accessible from display() in read only mode even without the global keyword. However if you assign None to the variable in func() without global keyword, you are creating a new local variable. Hence in display() you will see the unmodified global variable.
I am using some variable in multiple functions.
This includes changing the variable values by each of those functions.
I already declared the variable as 'global' in the first function.
Should I declare this variable again and again as global in each function (and this will not overwrite the first global variable I declared in the first function) or I should not declare it again as global in all those functions (but the local variables there still will be seen as global since I already declared this variable so first time)?
You can declare a variable as global in each function definition. Here's an example:
def f():
global x
x = 2
print x
x +=2
# This will assign a new value to the global variable x
def g():
global x
print x
x += 3
# This will assign a new value to the global variable x
f()
# Prints 2
g()
# Prints 4
print x
# Prints 7
The global keyword tells the parser per function that a name shouldn't be treated as a local when assigned to.
Normally any name you bind in a function (assign to, use as a function argument, use in an import statement in the function body, etc.) is seen by the parser as a local.
By using the global keyword, the parser will instead generate bytecode that'll look for a global name instead. If you have multiple functions that assign to the global, you'll need to declare that name global in all those functions. They'll then look up the name in the global namespace instead.
See the global statement documentation:
The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals.
and the Naming and Binding documentation:
If a name is bound in a block, it is a local variable of that block. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable.
Should I declare this variable again and again as global in each function
You should not have any global variables at all, and put these variables and functions into a class.
From the Python FAQ, we can read :
In Python, variables that are only referenced inside a function are implicitly global
And from the Python Tutorial on defining functions, we can read :
The execution of a function introduces a new symbol table used for the local variables of the function. More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names
Now I perfectly understand the tutorial statements, but then saying that variables that are only referenced inside a function are implicitly global seems pretty vague to me.
Why saying that they are implicitly global if we actually start looking at the local symbol tables, and then follow with the more 'general' ones? Is it just a way of saying that if you're only going to reference a variable within a function, you don't need to worry if it's either local or global?
Examples
(See further down for a summary)
What this means is that if a variable is never assigned to in a function's body, then it will be treated as global.
This explains why the following works (a is treated as global):
a = 1
def fn():
print a # This is "referencing a variable" == "reading its value"
# Prints: 1
However, if the variable is assigned to somewhere in the function's body, then it will be treated as local for the entire function body .
This includes statements that are found before it is assigned to (see the example below).
This explains why the following does not work. Here, a is treated as local,
a = 1
def fn():
print a
a = 2 # <<< We're adding this
fn()
# Throws: UnboundLocalError: local variable 'a' referenced before assignment
You can have Python treat a variable as global with the statement global a. If you do so, then the variable will be treated as global, again for the entire function body.
a = 1
def fn():
global a # <<< We're adding this
print a
a = 2
fn()
print a
# Prints: 1
# Then, prints: 2 (a changed in the global scope too)
Summary
Unlike what you might expect, Python will not fall back to the global scope it if fails to find a in the local scope.
This means that a variable is either local or global for the entire function body: it can't be global and then become local.
Now, as to whether a variable is treated as local or global, Python follows the following rule. Variables are:
Global if only referenced and never assigned to
Global if the global statement is used
Local if the variable is assigned to at least once (and global was not used)
Further notes
In fact, "implicitly global" doesn't really mean global. Here's a better way to think about it:
"local" means "somewhere inside the function"
"global" really means "somewhere outside the function"
So, if a variable is "implicitly global" (== "outside the function"), then its "enclosing scope" will be looked up first:
a = 25
def enclosing():
a = 2
def enclosed():
print a
enclosed()
enclosing()
# Prints 2, as supplied in the enclosing scope, instead of 25 (found in the global scope)
Now, as usual, global lets you reference the global scope.
a = 25
def enclosing():
a = 2
def enclosed():
global a # <<< We're adding this
print a
enclosed()
enclosing()
# Prints 25, as supplied in the global scope
Now, if you needed to assign to a in enclosed, and wanted a's value to be changed in enclosing's scope, but not in the global scope, then you would need nonlocal, which is new in Python 3. In Python 2, you can't.
Python’s name-resolution scheme is sometimes called the LEGB rule, after the scope
names.
When you use an unqualified name inside a function, Python searches up to four
scopes—the local (L) scope, then the local scopes of any enclosing (E) defs and
lambdas, then the global (G) scope, and then the built-in (B) scope—and stops at
the first place the name is found. If the name is not found during this search, Python
reports an error.
Name assignments create or change local names by default.
Name references search at most four scopes: local, then enclosing
functions (if any), then global, then built-in.
Names declared in global and nonlocal statements map assigned names
to enclosing module and function scopes, respectively.
In other words, all names assigned inside a function def statement (or a lambda) are locals by default. Functions can freely use names assigned
in syntactically enclosing functions and the global scope, but they must declare
such nonlocals and globals in order to change them.
Reference: http://goo.gl/woLW0F
This is confusing and the documentation could stand to be more clear.
"referenced" in this context means that a name is not assigned to but simply read from. So for instance while a = 1 is assignment to a, print(a) (Python 3 syntax) is referencing a without any assignment.
If you reference a as above without any assignment, then the Python interpreter searches the parent namespace of the current namespace, recursively until it reaches the global namespace.
On the other hand, if you assign to a variable, that variable is only defined inside the local namespace unless declared otherwise with the global keyword. So a = 1 creates a new name, a, inside the local namespace. This takes precedence over any other variable named a in higher namespaces.
Unlike some other languages, Python does not look up a variable name in a local symbol table and then fall back to looking for it in a larger scope if it's not found there. Variables are determined to be local at compile time, not at runtime, by being assigned to (including being passed in as a parameter). Any name that is not assigned to (and not explicitly declared global) is considered global and will only be looked for in the global namespace. This allows Python to optimize local variable access (using the LOAD_FAST bytecode), which is why locals are faster.
There are some wrinkles involving closures (and in Python 3, nonlocal) but that's the general case.
This question already has answers here:
Using global variables in a function
(25 answers)
Closed 8 months ago.
I'd like to be able to do something like this:
#mymodule
var = None
def load():
var = something()
Other module(s):
#secondmodule
import mymodule
mymodule.load()
#thirdmodule
from mymodule import var
print var #Shouldn't be None
But I don't know how to reference a modules variable from a function defined in the module.
Is this possible? Or am I going to need to put a global declaration in every place I wan't to use this.
Or am I going at this completely wrong?
Just change the function definition to:
def load():
global var # this line has been added to the original code
var = something()
Global variables are read-only from sibling methods. More accurately unless a variable is specified as global, Python consider it as local, but a read access to a local variable name will reach module-level scope if the name is not present in local scope.
See also use of “global” keyword in python and the doc for more details about the global statement
You seem to mostly have it. You are missing only the fact that "module-level" variables are called global in Python. (They are not truly global, but only global to the module they are declared in, in other words.)
In any function where you modify a global variable (you want to make the name refer to a different object), it must be declared global. So your load() function needs a global var at the beginning. If you are only using the value of a global variable, or if it is a mutable type such as a list and you are modifying it, but not changing the object that the name points to, you needn't declare it global.
The import statement is, as you have discovered, how you can import a module-level variable from one module into another.