Name Resolution
Time for the details
Global and Local Namespaces
These are commonly used terms
Let's try to understand the definitions
Global Namespaces
The global namespace is the namespace of the module currently being executed
To list this namespace, use
globals()
For example, suppose that we start the interpreter and begin making assignments
>>> x = 3
>>> dir()
['__builtins__', '__doc__', '__name__', 'x']
We are now working in the module
__main__
Hence the namespace for
__main__ is now the global namespace
Next, we import a module called
amodule>>> import amodule
The interpreter
- Creates a namespace for the module
- Starts executing commands in the module
The namespace
amodule.__dict__ is now the global namespace
Once execution of the module finishes, interpreter returns to the module from where the import statement was made
- In this case it's
__main__
Now the namespace of
__main__ is the global namespaceLocal Namespaces
Suppose that inside a module we have access to a function
fdef f(x):
a = 2
return a * x
Now we call the function
y = f(1)
The interpreter creates a local namespace for the function, and registers the variables in that namespace
Variables in the namespace are called local variables
After the function returns, the namespace is deallocated (lost)
We can view the contents of the local namespace with
locals()def f(x):
a = 2
print locals()
return a * x
Now we call the function
y = f(1)
{'a': 2, 'x': 1}
The __builtins__ Namespace
We have been using some built-in objects (mainly functions)
max(), dir(), str(), list(), len(), range(), type(), etc.
How does access to these names work?
- These definitions are stored in a module called
__builtin__ - They have there own namespace, called
__builtins__
>>> dir()
['__builtins__', '__doc__', '__name__']
>>> dir(__builtins__)
[... 'iter', 'len', 'license', 'list', 'locals', ...]
We can access elements of the namespace as follows
>>> __builtins__.max
<built-in function max>
But
__builtins__ is special, because we can access them directly as well:>>> max
<built-in function max>
>>> __builtins__.max == max
True
The reason why this works is explained in the next section...
Name resolution
When we reference a name, how does the Python interpreter find the corresponding value?
The Process of Name Resolution
At any point of execution, there are two or three namespaces which can be accessed directly
- Directly means without using a dot
pirather thanmath.pi
If the interpreter is not executing a function call then the namespaces are
- The global namespace (of the module being executed)
- The builtin namespace
Suppose that we refer to a name
print x
The interpreter
- First looks in the global namespace for
x - If it's not there, looks in the builtin namespace
- If it's not there, raises a
NameError
If the interpreter is executing a function call
y = f(1)
Then the namespaces are
- The local namespace of
f - The global namespace (of the module being executed)
- The builtin namespace
Now the interpreter
- First looks in the local namespace
- Then in the global namespace
- Then in the builtin namespace
- If it's not there, raises a
NameError
Consequences
Consider the script
test.pydef g(x):
a = 1
x = x + a
return x
a = 0
y = g(10)
print "a = ", a, "y = ", y
What happens when I run this script?
$ python -i test.py
a = 0 , y = 11
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
- The global namespace
{}is created - The function object is created,
gis bound to itgstored in the global namespace
- Next, the global variable
ais created, bound to0astored in the global namespace
- Next
gis called viay = g(10)- Local namespace
{}is constructed - Local
xandaare added to it- Local namespace =
{'x': 10, 'a': 1} x = x + auses the locala- Local
adoes not interfere with globala
- Local namespace =
- Local namespace
- After computations, return value assigned to
y - Local
xandaare discarded (namespace is deallocated)
Note that global
a was not affected by local a
Mutable Versus Immutable Parameters
Consider the following code segment
def f(x):
x = x + 1
return x
x = 1
print f(x), x
Prints 2 as the value of
f(x) and 1 as the value of xfis registered as a function in the global namespacexbound to 1 in the global namespace- Call
f(x)- Creates a local namespace
- Adds
xto local namespace, bound to 1 - Rebinds this local
xto the new integer object 2- The value 1 is now garbage collected
- Returns the value of local
x - Local namespace deallocated, local
xlost
- Prints the return value 2 for
f(x), and the value 1 for globalx
Different story when we use a mutable data type such as a list:
def f(x):
x[0] = x[0] + 1
return x
x = [1]
print f(x), x
Prints
[2] as the value of f(x) and same for xfis registered as a function in the global namespacexbound to[1]in the global namespace- Call
f(x)- Creates a local namespace
- Adds
xto local namespace, bound to[1] - The list
[1]is modified to[2] - Returns the list
[2] - Local namespace deallocated, local
xlost
- Global
xhas been modified
Conclusion: functions can modify global variables if they are mutable
0 comments:
Post a Comment