Learning Python - Mark Lutz [235]
# thismod.py
var = 99 # Global variable == module attribute
def local():
var = 0 # Change local var
def glob1():
global var # Declare global (normal)
var += 1 # Change global var
def glob2():
var = 0 # Change local var
import thismod # Import myself
thismod.var += 1 # Change global var
def glob3():
var = 0 # Change local var
import sys # Import system table
glob = sys.modules['thismod'] # Get module object (or use __name__)
glob.var += 1 # Change global var
def test():
print(var)
local(); glob1(); glob2(); glob3()
print(var)
When run, this adds 3 to the global variable (only the first function does not impact it):
>>> import thismod
>>> thismod.test()
99
102
>>> thismod.var
102
This works, and it illustrates the equivalence of globals to module attributes, but it’s much more work than using the global statement to make your intentions explicit.
As we’ve seen, global allows us to change names in a module outside a function. It has a cousin named nonlocal that can be used to change names in enclosing functions, too, but to understand how that can be useful, we first need to explore enclosing functions in general.
* * *
[38] Multithreading runs function calls in parallel with the rest of the program and is supported by Python’s standard library modules _thread, threading, and queue (thread, threading, and Queue in Python 2.6). Because all threaded functions run in the same process, global scopes often serve as shared memory between them. Threading is commonly used for long-running tasks in GUIs, to implement nonblocking operations in general and to leverage CPU capacity. It is also beyond this book’s scope; see the Python library manual, as well as the follow-up texts listed in the Preface (such as O’Reilly’s Programming Python), for more details.
Scopes and Nested Functions
So far, I’ve omitted one part of Python’s scope rules on purpose, because it’s relatively rare to encounter it in practice. However, it’s time to take a deeper look at the letter E in the LEGB lookup rule. The E layer is fairly new (it was added in Python 2.2); it takes the form of the local scopes of any and all enclosing function defs. Enclosing scopes are sometimes also called statically nested scopes. Really, the nesting is a lexical one—nested scopes correspond to physically and syntactically nested code structures in your program’s source code.
Nested Scope Details
With the addition of nested function scopes, variable lookup rules become slightly more complex. Within a function:
A reference (X) looks for the name X first in the current local scope (function); then in the local scopes of any lexically enclosing functions in your source code, from inner to outer; then in the current global scope (the module file); and finally in the built-in scope (the module builtins). global declarations make the search begin in the global (module file) scope instead.
An assignment (X = value) creates or changes the name X in the current local scope, by default. If X is declared global within the function, the assignment creates or changes the name X in the enclosing module’s scope instead. If, on the other hand, X is declared nonlocal within the function, the assignment changes the name X in the closest enclosing function’s local scope.
Notice that the global declaration still maps variables to the enclosing module. When nested functions are present, variables in enclosing functions may be referenced, but they require nonlocal declarations to be changed.
Nested Scope Examples
To clarify the prior section’s points, let’s illustrate with some real code. Here is what an enclosing function scope looks