Accessing module level variables, from within a function in the module [duplicate] - python

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.

Related

Accessing global variable in local environment

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.

Global variable used inside a instance method without "global" [duplicate]

This question already has answers here:
Why isn't the 'global' keyword needed to access a global variable?
(11 answers)
Closed 7 years ago.
I thought global variables inside a Python function had to be declared global. So why does the following compile and run without error?
#!/usr/bin/env python
text = "why is this seen?"
class Foo:
def doit(self):
print(text)
x = Foo()
x.doit()
I'd appreciate a citation to the Python3 manual if possible.
You asked for a reference to the Python 3 manual. I've bolded the section that says you don't need to use the global keyword to reference free variables.
https://docs.python.org/3/reference/simple_stmts.html?highlight=global#grammar-token-global_stmt
7.12. The global statement
global_stmt ::= "global" identifier ("," identifier)*
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. It would be impossible to assign to a
global variable without global, although free variables may refer to
globals without being declared global.
Note that in most code all of the classes and functions that you reference are globals (or builtins) but you didn't think twice about not needing global print before calling it.
Its all about scope, since text is declared outside, free from any class or function, it can be reached from anywhere. To get a better idea, consider these two examples:
#!/usr/bin/env python
text = "why is this seen?"
class Foo:
def doit(self):
text = "this is changed"
print(text)
x = Foo()
x.doit()
print text
In the above example, we overwrite the text variable locally, in the Foo, class, but the global instance of text is the same. But in this instance:
#!/usr/bin/env python
text = "why is this seen?"
class Foo:
def doit(self):
global text
text = "this is changed"
print(text)
x = Foo()
x.doit()
print text
We declare that we want the global version of text and then we can modify it.
BUT: global variables are frowned upon, consider using input arguments to functions and returning new values instead of having variable globally accessible everywhere
The right way to do it:
#!/usr/bin/env python
class Foo:
text = "why is this seen?"
def doit(self):
print(self.text)
x = Foo()
x.doit()
Have text encapsulated in the class!
You don't need to specify a variable using global if you just need to access it. You can do that without a global.
Here, Python will look in the class Foo scope first for the text variable. Since, it does not find the variable text in the Foo class so it will look into outer scope. Now, it finds the variable text, so it uses that value to print the output.
According to Python docs, at any time during execution, there are at least three nested scopes whose namespaces are directly accessible:
the innermost scope, which is searched first, contains the local names
the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also
non-global names
the next-to-last scope contains the current module’s global names
the outermost scope (searched last) is the namespace containing built-in names

Python : Why is it said that variables that are only referenced are implicitly global?

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.

"local variable referenced before assignment" — only functions?

Take the following code:
import something
def Foo():
something = something.SomeClass()
return something
…this is apparently not valid code:
UnboundLocalError: local variable 'something' referenced before assignment
…as the local variable something is created, but not assigned, before the RHS of the = is evaluated. (See, for example, this related answer's comment.) This seems a bit odd to me, but sure, I'll go with it. Now, why is the following valid code?
class Foo(object):
something = something.SomeClass()
My understanding was that the inside of a class definition was essentially a scope:
The class’s suite is then executed in a new execution frame (see section Naming and binding), using a newly created local namespace and the original global namespace.
So, then, why does that code act differently than that of a function?
From the python class documentation:
Class definitions place yet another namespace in the local scope.
A special quirk of Python is that – if no global statement is in effect – assignments to names always go into the innermost scope. Assignments do not copy data — they just bind names to objects. The same is true for deletions: the statement del x removes the binding of x from the namespace referenced by the local scope. In fact, all operations that introduce new names use the local scope: in particular, import statements and function definitions bind the module or function name in the local scope. (The global statement can be used to indicate that particular variables live in the global scope.)
So within a function (or a scope) the assignment creates a local unbound variable that is accessed before it is bound, whereas in a class definition it creates an entry in the "namespace" dictionary of that class on assignment, allowing the resolution of something to the outer namespace (the module namespace).
Consider the following example which may help to clarify this:
import datetime
class Foo(object):
datetime = datetime.datetime
>>> datetime
<module 'datetime' from '/usr/lib/python2.6/lib-dynload/datetime.so'>
>>> Foo.datetime
<type 'datetime.datetime'>
Note that the line datetime = datetime.datetime is actually assigning to the name Foo.datetime, which is not ambiguous with the global datetime (like it would be if the same code were in the function).
In summary, because class definitions create a new namespace as well as a new scope, you are allowed to directly access a name in an enclosing scope and assign to the same name in the local scope.

Why is a variable able to be defined after definition of function using it?

I have a very simple and maybe dumb question:
Why does this work?
def print_list():
for student in student_list:
print(student)
student_list = ["Simon", "Mal", "River", "Zoe", "Jane", "Kaylee", "Hoban"]
print_list()
The way I've come to know functions and arguments, the function print_list() shouldn't recognize student_list since I didn't assign it as an argument for the function.
By the time you're calling print_list(), you have student_list defined as a global variable.
In Python, variables are created when you assign them. In your case, student_list is assigned in the global scope, so it is a global variable. (The global scope is the stuff that isn't inside your function.)
When Python encounters a variable inside a function that is not a local variable (that is, it was not passed in as an argument and was not assigned inside the function), it automatically looks for the variable in the global scope.
If you are wondering what the purpose of the global statement is, since global variables are already visible inside functions: global allows you to reassign a global variable, and have it take effect globally. For example:
def b():
global a
a = 5
a = 4
print(a) # prints 4
b()
print(a) # prints 5
In most cases, you don't need the global statement, and I would recommend that you don't use it, especially until you are much more experienced in Python. (Even experienced Python programmers tend not to use global very much, though.)
The way I understand it is that your program has 3 parts
define print_list()
initialise student_list (global variable)
call print_list()
When you call print_list(), student_list is already there. Also, in a function you have the scopes where a variable (student_list) is searched:
1. local scope (it'll fail because you don't have it defined, only referred)
2. global scope (it'll succeed, because it was just initialised

Categories