Scope and Modules#
Namespaces#
Python programs are constructed from code blocks
Note: cells in a Python notebook are not blocks
Examples of code blocks in Python
A function body
A module
…
A namespace is a mapping (like a dictionary) from variable names to objects
Each block is associated with a namespace
Types of namespaces in Python:
Local namespace
Enclosing namespace
Global namespace
Built-ins namespace
A built-ins namespace is created at the beginning of each program and is never deleted
A global namespace is created for every Python program and module
__main__
is the default module, all code that does not belong to any named module is made part of thisCreated when the module is imported (i.e., read in) and normally lasts until the interpreter is quit
A local namespace is created for a function whenever it is called and destroyed when it returns
Scope#
Scope is the code region where a specific namespace is accessible
Defines the visibility of a variable name within a block
Allows for reuse of variable names in different blocks
When accessing a variable through its name, Python interpreter searches, in order,
Local namespace
Inherited enclosing local namespace(s)
Global namespace
Built-ins namespace

def somefunction():
x = 3
return x
x = 4
#def print(x):
# return x*2
type(print)
builtin_function_or_method
dir(__builtins__)
Shows the variable names in the built-ins namespace
globals()
Returns a dictionary with variable names for the keys and the objects they refer to as values
locals()
Returns a dictionary with local variable names and their objects in the current scope
dir()
Returns the variable names in the local namespace as a
list
object
def f():
pass
globals()
{'__name__': '__main__',
'__doc__': 'Automatically created module for IPython interactive environment',
'__package__': None,
'__loader__': None,
'__spec__': None,
'__builtin__': <module 'builtins' (built-in)>,
'__builtins__': <module 'builtins' (built-in)>,
'_ih': ['',
'def somefunction():\n x = 3\n return x\nx = 4\n#def print(x):\n# return x*2\ntype(print)',
'def f():\n pass\nglobals()'],
'_oh': {1: builtin_function_or_method},
'_dh': [PosixPath('/home/runner/work/EngineeringComputations/EngineeringComputations/engineering_computations')],
'In': ['',
'def somefunction():\n x = 3\n return x\nx = 4\n#def print(x):\n# return x*2\ntype(print)',
'def f():\n pass\nglobals()'],
'Out': {1: builtin_function_or_method},
'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x7f68fc10b7d0>>,
'exit': <IPython.core.autocall.ZMQExitAutocall at 0x7f68fc11bd50>,
'quit': <IPython.core.autocall.ZMQExitAutocall at 0x7f68fc11bd50>,
'open': <function io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)>,
'_': builtin_function_or_method,
'__': '',
'___': '',
'_i': '\ndef somefunction():\n x = 3\n return x\nx = 4\n#def print(x):\n# return x*2\ntype(print)',
'_ii': '',
'_iii': '',
'_i1': '\ndef somefunction():\n x = 3\n return x\nx = 4\n#def print(x):\n# return x*2\ntype(print)',
'somefunction': <function __main__.somefunction()>,
'x': 4,
'_1': builtin_function_or_method,
'_i2': 'def f():\n pass\nglobals()',
'f': <function __main__.f()>}
Examples
def hello():
name = input("Enter your name: ")
greeting = "Hello " + name + "!"
print(greeting)
hello()
---------------------------------------------------------------------------
StdinNotImplementedError Traceback (most recent call last)
Cell In[3], line 6
3 greeting = "Hello " + name + "!"
4 print(greeting)
----> 6 hello()
Cell In[3], line 2, in hello()
1 def hello():
----> 2 name = input("Enter your name: ")
3 greeting = "Hello " + name + "!"
4 print(greeting)
File /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/ipykernel/kernelbase.py:1281, in Kernel.raw_input(self, prompt)
1279 if not self._allow_stdin:
1280 msg = "raw_input was called, but this frontend does not support input requests."
-> 1281 raise StdinNotImplementedError(msg)
1282 return self._input_request(
1283 str(prompt),
1284 self._parent_ident["shell"],
1285 self.get_parent("shell"),
1286 password=False,
1287 )
StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
print(greeting)
Reason for the exception in the above cell is the scope of the variable
greeting
is local to the user-defined functionhello
greeting = "Hello World!"
def hello():
name = input("Enter your name: ")
greeting = "Hello " + name + "!"
print(greeting)
hello()
print(greeting)
This code works now because there are two variables named
greeting
The variable
greeting
in the first line of the cell is in the global scopeThe variable in the function
hello
is still in the local scope
PI = 3.1415926
def circle_area(diameter):
def square(x):
return x*x
area = 0.25*PI*square(diameter)
return area
The variable
PI
can be used within thecircle_area
function as it is defined in the global namespace
circle_area(4)
square(2)
An exception is raised when the
square
function is called as the function definition is in the local scope ofcircle_area
function
x = 10 # global x
print('x' in globals())
def f(x):
x = 20 # local in f
print(locals())
print(globals()['x'], x, '\n', sep='\t\t')
def g(x):
#x = 30 # local in g
print(locals())
print(globals()['x'], x, sep='\t\t')
g(x)
f(x)
Modules#
Modules are a set of Python definitions and statements that can be reused across different programs or interactive sessions
E.g., os, sys, math, random, timeit
Enable reuse of functions, classes etc.
Packages are a set of modules
E.g., numpy, scipy, matplotlib, …
You can create your own user-derfined modules
The
import
statement is used to import the contents of a moduleTypically, at the beginning of a Python program/script
Modules are Python objects that have their own namespace
Shared by the functions defined within the module
Each of these functions will have its own local namespace when called
Python installation comes with certain built-in modules contained in the Python standard library
More modules or packages are hosted on the Python package index
The tool pip is used to manage (install/uninstall/modify) the external modules or packages
If both python2 and python3 are installed, then pip3 should be used
General installation: type
pip install module_name
into the terminal
Some useful modules from the Python standard library
math – mathematical functions
cmath – mathematical functions for complex numbers
decimal – fast, more accurate floating-point arithmetic
random – pseudo-random number generation
statistics – statistical functions like mean, median, stdev, variance etc.
os – access functions for files and directories, execute OS commands etc.
os.path – sub-module for manipulating pathnames, check existence of a file or directory etc.
Provides an OS-independent interface and thus, makes the Python code portable
sys – a module to interact with the Python interpreter
timeit – measure execution time of small bits of python code
…
Importing modules
import module_name as alias
as
is a Python keywordas alias
part is optional and is used when two modules have the same name
Examples:
import math # No alias
import numpy as np # np is an alias to the numpy module
Accessing variables or functions defined within the module’s namespace:
When no alias is used:
module_name.some_func()
When an alias is used:
alias.some_func()
dir(module_name)
gives list of objects within the modulehelp(module_name)
gives information about moduleAlso provides breakdown of function and data within module
import math
type(math)
globals()['math']
print(dir(math)) # Using print here just for better formatting, not required
help(math.comb)
math.cos(math.pi/3)
Importing everything from the module into the current global namespace
from module_name import *
When imported this way, the functions and variables defined in the module can be accessed directly (e.g.,
cos(pi)
instead ofmath.cos(math.pi)
)
Discouraged as this leads to unreadable code and potential conflicts with identifiers
import math
math.sqrt(-1)
math
module cannot handle complex arithmetic, butcmath
does
import cmath
cmath.sqrt(-1)
If everything from both modules are loaded simultaneously, only one of the identically named functions (like
sqrt
) from the module imported later can be used
from cmath import *
from math import *
sqrt(-1) # From math module
Selectively importing parts of modules
from module_name import object1, object2, ... , objectN
Imports various objects (functions, classes etc.) defined in the module
The objects are imported to the global namespace and can be directly accessed
Module name is not needed to access the imported objects
E.g.,
from math import cos, sin, tan, pi
Each selectively imported object can be given an alias to prevent conflicts with existing identifiers with the as keyword
from module_name import object1 as alias1, ... , objectN as aliasN
The as keyword can be omitted as needed
E.g.,
from math import cos as math_cos, pi
import math
pi = math.pi
cos = math.cos
cos(pi)
del math
The
del
statement removes objects from the global namespace
from math import cos, pi
cos(pi)
#option 1
import math
cos = math.cos
#option 2
from math import cos
#multi import w/ alias
from math import cos as mathcos, sin, pi
mathcos(pi)
User Defined Modules#
To create a custom module named myModule:
Save the data, function, and class definitions to a file named myModule.py
Add the directory to the module search path defined by sys.path
Not needed if saved to the current directory or one of the existing module search paths
For a more permanent solution, add the directory to the PYTHONPATH environment variable
import sys
sys.path.append('/home/narasimha/python_notebooks/ME241/')
import myModule
dir(myModule)
print(myModule)
#myMod.x
#myMod.myFun()
import sys
sys.path.append('secret_subfolder')
import myMod2
myMod2.secret()
sys.path.append('/home/jupyter-jsteffens/')
import myMod3
myMod3.super_secret()
Example
A simple module for element-wise addition and multiplication of
list
s
# User Module for doing math on lists
repeat = 1
def addLists(list1, list2):
'''Function for adding lists'''
if len(list1) != len(list2):
print("Lists should be of the same size!")
list3 = []
for i in range(len(list1)):
list3.append(list1[i] + list2[i])
return repeat*list3
def multLists(list1, list2):
'''Function for multiplying lists'''
if len(list1) != len(list2):
print("Lists should be of the same size!")
list3 = []
for i in range(len(list1)):
list3.append(list1[i] * list2[i])
return repeat*list3
listMod.py is located in the current directory, do not need to call
sys.path.append()
import listMod
help(listMod)
listMod.repeat = 2
l1 = [1, 2, 3, 4, 5]
l2 = [2, 4, 6, 8, 10]
listMod.multLists(l1, l2)