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
f
def 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
pi
rather 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.py
def 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,
g
is bound to itg
stored in the global namespace
- Next, the global variable
a
is created, bound to0
a
stored in the global namespace
- Next
g
is called viay = g(10)
- Local namespace
{}
is constructed - Local
x
anda
are added to it- Local namespace =
{'x': 10, 'a': 1}
x = x + a
uses the locala
- Local
a
does not interfere with globala
- Local namespace =
- Local namespace
- After computations, return value assigned to
y
- Local
x
anda
are 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 x
f
is registered as a function in the global namespacex
bound to 1 in the global namespace- Call
f(x)
- Creates a local namespace
- Adds
x
to local namespace, bound to 1 - Rebinds this local
x
to the new integer object 2- The value 1 is now garbage collected
- Returns the value of local
x
- Local namespace deallocated, local
x
lost
- 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 x
f
is registered as a function in the global namespacex
bound to[1]
in the global namespace- Call
f(x)
- Creates a local namespace
- Adds
x
to local namespace, bound to[1]
- The list
[1]
is modified to[2]
- Returns the list
[2]
- Local namespace deallocated, local
x
lost
- Global
x
has been modified
Conclusion: functions can modify global variables if they are mutable
0 comments:
Post a Comment