Sunday, February 12, 2017

Namespaces and Scope

Variable name also called identifier is simply a name given to objects. Everything in Python is an object. So name is a way to access specific object.  Let’s define a variable a and assign value of 5 (a = 5) . Here 5 is an object stored in primary memory or RAM (RAM is short for Random Access Memory) and a is the name we associate it with. We can get the address of some object through the built-in function id().
>>> a = 5
>>> print 'id(a) = ' + str(id(a))
id(a) = 8420656

Id value may be different on your computer. Besides variable a we can also check out the memory address of variable 5 .
>>> a = 5
>>> print 'id(a) = ' + str(id(a))
id(a) = 8420656
>>> print 'id(5) = ' + str(id(5))
id(5) = 8420656

As you can see they both refer to the same object. Now we will add a with 1 and then check the id() of variable a, and it’s value, and finally we’ll define new variable b and assign value of 5.
>>> a = 5
>>> print 'id(a) = ' + str(id(a))
id(a) = 8420656
>>> print 'id(5) = ' + str(id(5))
id(5) = 8420656
>>> a = a + 1
>>> print 'id(a) = ' + str(id(a))
id(a) = 8420644
>>> print 'id(6) = ' + str(id(6))
id(6) = 8420644
>>> b = 5
>>> print 'id(b) = ' + str(id(b))
id(b) = 8420656
First we’ve created object 5 and the name a is associated with it, when we add one to variable a, then a new object 6 is created and now a associates with this object. Id(a) and id(6) have the same value. When we created object 5 and assign value of b to it and then check it’s id. As you can see it has the same value as the number 5.
This is efficient as Python doesn’t have to create a new duplicate object. This property makes Python very powerful so name could refer to any type of object.
>>> a = 5
>>> print 'id(a) = ' + str(id(a))
id(a) = 8420656
>>> a = 'Hello World!'
>>> print 'id(a) = ' + str(id(a))
id(a) = 38299392
>>> a = [1, 2, 3, 4, 5, 6]
>>> print 'id(a) = ' + str(id(a))
id(a) = 38366864
Three different types of objects have been assign to variable a and each time the id value was different, because the data is temporarily stored on different memory address.
Functions are also objects, so the name of the function can refer to them as well. Now we’ll define a function call printHello(). From the name of the function you can guess what the function does.
>>> def printHello():
...     print 'Hello'
...
>>> a = printHello()
Hello

Our name a can refer to a function ad we can call the function through it, pretty neat. 

What is a namespace?

Now that you’ve understood what names are, we’re moving on to the concept of namespaces. Strictly speaking a namespace is a collection of names. In Python you can imagine a namespaces as a mapping of every name, you have defined, to corresponding objects. Different namespaces can co-exist at a given time but are completely isolated. When we start Python a namespace containing all the built-in names is created and exists as long as we don’t exit the Python.
Built-in function such as id(), print(), type(), list(), dict()  and others are always at disposal to us from any part of the program. Each module creates its own global namespace. These different namespace are isolated so the same name that may exist in different modules do not collide.
Modules can have various functions and classes. A local namespace is created when a function is called, which has all the names defined in it. Similar, is the case with class

What is scope?
Although there are various unique namespaces defined, we may not be able to access all of them from every part of the program. It’s time to introduce variable scope.
Scope is a portion of the program from where a namespace can be accessed directly without any prefix. At any given moment there are at least three nested scopes.
  1. Scope of the current function which has local names
  2. Scope of the module which has global names
  3. Outermost scope which has built-in names.

When a reference is made inside the function, the name is searched in the local namespace, then in the global namespace and finally in the built-in namespace. If we have function inside the function which is called a nested function then a new scope is nested inside the local scope. The example is shown below.
>>> def outerfunction():
...     b = 20
...     def innerfunction():
...         c = 30
...
>>> a = 10
In previous example the variable a is in the global namespace, variable b is in the local namespace of outerfunction() and c is in the nested local namespace of innerfunction(). When we’re inside the innerfunction(), variable c is local variable, while variable b is nonlocal and a is global variable. We can read as well as assign new values to c but can only read b and c from innerfunction(). If we try to assign as a value to b, a new variable b is created in the local namespace which is different than the nonlocal b. Same thing happen when we assign a value to a. However, if we declare a as global, all the reference and assignment go to global a. Similarly, if we want to rebind the variable b, it must be declared as nonlocal. The following example will further clarify this.
>>> def outerfunction():
...     a = 20
...     def innerfunction():
...         a = 30
...     print 'a = ', a
...
>>> outerfunction()
a =  20









No comments:

Post a Comment