Home      |       Contents       |       About

Prev: - Language execution model      |       Next: Variables and Dynamic typing

Namespaces and Modules

(a) Object reference

  • It is of paramount importance in learning Python to clearly understand what happens 'under the hood' when an assignment command is executed. So:

What happens when 'x = 1' is executed?

  • Three actions are taken:
    • (a) a name 'x' (a simple sequence of characters, an identifier) is created somewhere in the system memory
    • (b) an object (a specific data structure) with value '1' is created somewhere in memory
    • (c) a binding between name x and object '1' is established (that is: a pointer is created directing from 'x' to '1')

This binding is typically called 'object reference'

Pythontutor

  • It is advisable to use online pythontutor to visualize execution of Python code

  • See how pythontutor visualizes object reference

Shared object reference

  • See that two (or even more names, a and c in this example) may reference the same object (integer '1'). This is typically called "shared object reference"

Source

(b) Namespaces

What is a namespace?

  • In Python a 'namespace' is a mapping from names to their objects (values) in a specific programming context. For example, the mapping of names a, b, c, d in the example above on objects 1, 3 and 'spam' constructs a namespace.
  • A namespace can be also conceptualized as the 'ecosystem' where a name is born, lives and dies.
  • A concrete example:
    • x = 1 (a name is almost always created ('is born') by some assignment command)
    • x = 'spam' (other assignments may alter the name binding, that is its 'object reference')
    • del x (one way for a name to 'die' - that is, expelled from the namespace- is by using the 'del' command)
In [7]:
x=1
x='spam'
print(x)

del x
print(x)
spam
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-7-2bb509689422> in <module>()
      4 
      5 del x
----> 6 print(x)

NameError: name 'x' is not defined
  • x=1 introduces 'x' in the namespace but name 'x' is not recognized after executing the 'del x' command. 'x' is deleted from the namespace.

Printing values onscreen

  • Please note that when working interactively in a Python shell (like, for example, jupyter notebook) you may either use the print() function to present values onscreen or simply write the name or expression whose value you want in the output.
  • In the latter case only the last expression in the cell will be presented in the output unless you define otherwise by adjusting the notebook settings
In [1]:
x = 1
y = 2.5
x + y
# Just writing the expression will present the outcome 
Out[1]:
3.5
In [5]:
x = 1
y = 2.5
print(x, y, 2*x**y)
# Better use print() when you want to present more than one values 
1 2.5 2.0

(c) Modules

What is a module?

  • A module is practically any .py file containing useful code (for example: statements, functions, and classes) that can be used for code development.
  • As the name implies, modules promote the idea of modular development in practice. Python offers a simple yet powerful way to link modules and use/reuse code in many different situations

How to connect modules

  • Modules are connected using the 'import' command
  • Typically you write the import command in the beginning (not necessarily though) of your main program module, as follows:
      import module_name 
  • The 'import' command imports the namespace of the module to the namespace of the code you are writing in your main program. For example:
In [ ]:
import random

print(random.randint(1,10))
  • The 'random' module offers functions for generating and managing random numbers. The 'import random' command imports the namespace of 'random' in your program code. We shall see more of that later.
  • Note the use of 'dot notation' to refer to the imported names: 'module_name.imported_name'. This is a practical way to visualize namespaces and import them safely in your code.
  • There are two other common ways to write the 'import' command. One you should avoid; the other you should follow.
  • Avoid this:
In [4]:
from random import *  
print(randint(1,10))  
  • The benefit here is that you import the entire module namespace and you can use it without writing the module name as a prefix.
  • However: this technique provides no visual cues as to the origin of the names and it may confuse you - so avoid it unless you are completely confident about your code!
  • Follow this:
In [6]:
import random as rn  
print(rn.randint(1,10))
  • This technique allows you to:
    • (a) Use a two-letter alias for the imported module, so the overload from writing the prefix is minimized
    • (b) You still have a visual cue about the namespace. You easily understand, for example, that the 'randint' function comes from the 'rn' module and this is a very very useful information in developing and debugging.

. Free learning material
. See full copyright and disclaimer notice