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

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

Related

Python Reference Language: nonlocal definition

In this paragraph, one can find the following sentence (my emphasis):
Names listed in a nonlocal statement, unlike those listed in a global statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot be determined unambiguously).
I take the bold-ed sentence in the parenthesis to explain the previous sentence meaning that in order for a nonlocal statement such as nonlocal a to be correct, a statement such as a = 1 should have problems deciding in what namespace to add (or modify) the binding, either in the local namespace or in an enclosing namespace (because there exists such a namespace already containing the binding for name a).
Is this correct, is that the intention?
If yes, I believe that the wording (in the parenthesis) would hold even for cases in which a is global, as "the scope in which a new binding should be created cannot be determined unambiguously", which is not intended. Am I correct?
The language reference is saying that some statement in an outer scope must create the variable for nonlocal to refer to. For example, this is fine:
def f():
def g():
a = 3
def h():
def i():
nonlocal a
print(a)
but this is not:
def f():
def g():
def h():
def i():
nonlocal a
print(a)
because in the first snippet, Python can tell that nonlocal should use the a variable from the g function. In the second snippet, Python would have to create a new a variable in one of the enclosing functions, and it can't tell which.

Scope in Functions vs. Methods [duplicate]

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 8 years ago.
I am wondering why a method of a class doesn't look into its enclosing scope, if a name is not defined.
def test_scope_function():
var = 5
def print_var():
print(var) # finds var from __test_scope_function__
print_var()
globalvar = 5
class TestScopeGlobal:
var = globalvar # finds globalvar from __main__
#staticmethod
def print_var():
print(TestScopeGlobal.var)
class TestScopeClass():
var = 5
#staticmethod
def print_var():
print(var) # Not finding var, raises NameError
test_scope_function()
TestScopeGlobal.print_var()
TestScopeClass.print_var()
I would expect TestScopeClass.print_var() to print 5 since it can read classvar in the TestScopeClass body.
Why this behavior? And what should i read in the docs to get to know about it.
Scopes are searched as follows:
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
(emphasis added). Enclosing classes are not searched, because they are not listed. This behavior is deliberate, because otherwise the descriptor protocol, which among other things provides the self argument to methods, would not have a chance to fire.
Per the Python documentation (emphasis mine):
The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods

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.

Why doesn't Python's nonlocal keyword like the global scope?

In Python 3.3.1, this works:
i = 76
def A():
global i
i += 10
print(i) # 76
A()
print(i) # 86
This also works:
def enclosing_function():
i = 76
def A():
nonlocal i
i += 10
print(i) # 76
A()
print(i) # 86
enclosing_function()
But this doesn't work:
i = 76
def A():
nonlocal i # "SyntaxError: no binding for nonlocal 'i' found"
i += 10
print(i)
A()
print(i)
The documentation for the nonlocal keyword states (emphasis added):
The nonlocal statement causes the listed identifiers to refer to
previously bound variables in the nearest enclosing scope.
In the third example, the "nearest enclosing scope" just happens to be the global scope. So why doesn't it work?
PLEASE READ THIS BIT
I do notice that the documentation goes on to state (emphasis added):
The [nonlocal] statement allows encapsulated code to
rebind variables outside of the local scope besides the global
(module) scope.
but, strictly speaking, this doesn't mean that what I'm doing in the third example shouldn't work.
The search order for names is LEGB, i.e Local, Enclosing, Global, Builtin. So the global scope is not an enclosing scope.
EDIT
From the docs:
The nonlocal statement causes the listed identifiers to refer to
previously bound variables in the nearest enclosing scope. This is
important because the default behavior for binding is to search the
local namespace first. The statement allows encapsulated code to
rebind variables outside of the local scope besides the global
(module) scope.
why is a module's scope considered global and not an enclosing one? It's still not global to other modules (well, unless you do from module import *), is it?
If you put some name into module's namespace; it is visible in any module that uses module i.e., it is global for the whole Python process.
In general, your application should use as few mutable globals as possible. See Why globals are bad?:
Non-locality
No Access Control or Constraint Checking
Implicit coupling
Concurrency issues
Namespace pollution
Testing and Confinement
Therefore It would be bad if nonlocal allowed to create globals by accident. If you want to modify a global variable; you could use global keyword directly.
global is the most destructive: may affect all uses of the module anywhere in the program
nonlocal is less destructive: limited by the outer() function scope (the binding is checked at compile time)
no declaration (local variable) is the least destructive option: limited by inner() function scope
You can read about history and motivation behind nonlocal in PEP: 3104
Access to Names in Outer Scopes.
It depends upon the Boundary cases:
nonlocals come with some senstivity areas which we need to be aware of. First, unlike the global statement, nonlocal names really must have previous been assigned in an enclosing def's scope when a nonlocal is evaluated or else you'll get an error-you cannot create them dynamically by assigning them anew in the enclosing scope. In fact, they are checked at function definition time before either or nested function is called
>>>def tester(start):
def nested(label):
nonlocal state #nonlocals must already exist in enclosing def!
state = 0
print(label, state)
return nested
SyntaxError: no binding for nonlocal 'state' found
>>>def tester(start):
def nested(label):
global state #Globals dont have to exits yet when declared
state = 0 #This creates the name in the module now
print(label, state)
return nested
>>> F = tester(0)
>>> F('abc')
abc 0
>>> state
0
Second, nonlocal restricts the scope lookup to just enclosing defs; nonlocals are not looked up in the enclosing module's global scope or the built-in scope outside all def's, even if they are already there:
for example:-
>>>spam = 99
>>>def tester():
def nested():
nonlocal spam #Must be in a def, not the module!
print('current=', spam)
spam += 1
return nested
SyntaxError: no binding for nonlocal 'spam' found
These restrictions make sense once you realize that python would not otherwise generally know enclosing scope to create a brand-new name in. In the prior listing, should spam be assigned in tester, or the module outside? Because this is ambiguous, Python must resolve nonlocals at function creation time, not function call time.
The answer is that the global scope does not enclose anything - it is global to everything. Use the global keyword in such a case.
Historical reasons
In 2.x, nonlocal didn't exist yet. It wasn't considered necessary to be able to modify enclosing, non-global scopes; the global scope was seen as a special case. After all, the concept of a "global variable" is a lot easier to explain than lexical closures.
The global scope works differently
Because functions are objects, and in particular because a nested function could be returned from its enclosing function (producing an object that persists after the call to the enclosing function), Python needs to implement lookup into enclosing scopes differently from lookup into either local or global scopes. Specifically, in the reference implementation of 3.x, Python will attach a __closure__ attribute to the inner function, which is a tuple of cell instances that work like references (in the C++ sense) to the closed-over variables. (These are also references in the reference-counting garbage-collection sense; they keep the call frame data alive so that it can be accessed after the enclosing function returns.)
By contrast, global lookup works by doing a chained dictionary lookup: there's a dictionary that implements the global scope, and if that fails, a separate dictionary for the builtin scope is checked. (Of course, writing a global only writes to the global dict, not the builtin dict; there is no builtin keyword.)
Theoretically, of course, there's no reason why the implementation of nonlocal couldn't fall back on a lookup in the global (and then builtin) scope, in the same way that a lookup in the global scope falls back to builtins. Stack Overflow is not the right place to speculate on the reason behind the design decision. I can't find anything relevant in the PEP, so it may simply not have been considered.
The best I can offer is: like with local variable lookup, nonlocal lookup works by determining at compile time what the scope of the variable will be. If you consider builtins as simply pre-defined, shadow-able globals (i.e. the only real difference between the actual implementation and just dumping them into the global scope ahead of time, is that you can recover access to the builtin with del), then so does global lookup. As they say, "simple is better than complex" and "special cases aren't special enough to break the rules"; so, no fallback behaviour.

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

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.

Categories