class: center, middle .center[] # Python Course: Modules Shahid Beheshti University Instructor: S. M. Masoud Sadrnezhaad --- # Python Modules - A module allows you to **logically organize your Python code**. - Grouping related code into a module makes the code **easier to understand and use**. - A module is a **file consisting of Python code**. - The **file name is the module name** with the **suffix .py** appended. - A module can define **functions, classes, variables and runnable code**. - You may also want to **use a handy function** that you’ve written in several programs **without copying its definition** into each program. --- class: split-50 # The import Statement - The import has the following syntax: ```python import module1[, module2[,... moduleN] ```
.column[ - You can use **any Python source file as a module** by executing an **import statement in some other Python source file**. - This does not enter the names of the functions defined directly in the current **symbol table**; it **only enters the module name** there. - A module is **loaded only once**, regardless of the number of times it is imported. This prevents the module execution from happening over and over again if multiple imports occur. ] .column[ Create a **file called `fibo.py`** in the current directory: ```python def fib(n): # write Fibonacci series up to n a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a+b print() ``` Using the **module name** you can access the functions: ```python import fibo fibo.fib(1000) ``` ]
--- # The from...import Statement Python's from statement lets you import specific attributes from a module into the current namespace. The from...import has the following syntax − ```python from modname import name1[, name2[, ... nameN]] ``` For example, to import the function fibonacci from the module fib, use the following statement − ```python from fib import fibonacci ``` This statement does not import the entire module fib into the current namespace; it just introduces the item fibonacci from the module fib into the global symbol table of the importing module. --- # The from...import * Statement: It is also possible to import all names from a module into the current namespace by using the following import statement − ```python from modname import * ``` This provides an easy way to import all the items from a module into the current namespace; however, this statement should be used sparingly. --- # Locating Modules - When the **interpreter** encounters an import statement, it imports the module if the **module is present in the search path**. - When you import a module, the Python **interpreter searches for the module** in the **following sequences** − * The current directory. * If the module isn't found, Python then searches each directory in the shell variable PYTHONPATH. * If all else fails, Python checks the default path. On UNIX, this default path is normally /usr/local/lib/python/. - The module search path is stored in the system module sys as the **sys.path variable**. - The sys.path variable contains the current directory, **PYTHONPATH**, and the installation-dependent default. --- # The PYTHONPATH Variable: The PYTHONPATH is an environment variable, consisting of a list of directories. The syntax of PYTHONPATH is the same as that of the shell variable PATH. Here is a typical PYTHONPATH from a **Windows system**: ```python set PYTHONPATH=c:\python20\lib; ``` And here is a typical PYTHONPATH from a **UNIX system**: ```python set PYTHONPATH=/usr/local/lib/python ``` --- # The dir( ) Function The **dir() built-in function** returns a **sorted list of strings** containing the **names defined by a module**. ```python import math content = dir(math) print(content) ``` When the above code is executed, it produces the following result − ```python ['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] ``` --- # The math Module The math module contains the kinds of **mathematical functions** you’d typically find on **your calculator**. ```python >>> import math >>> math.pi # Constant pi 3.141592653589793 >>> math.e # Constant natural log base 2.718281828459045 >>> math.sqrt(2.0) # Square root function 1.4142135623730951 >>> math.radians(90) # Convert 90 degrees to radians 1.5707963267948966 >>> math.sin(math.radians(90)) # Find sin of 90 degrees 1.0 >>> math.asin(1.0) * 2 # Double the arcsin of 1.0 to get pi 3.141592653589793 ``` --- # The random Module ```python import random # Create a black box object that generates random numbers rng = random.Random() dice_throw = rng.randrange(1,7) # Return an int, one of 1,2,3,4,5,6 delay_in_seconds = rng.random() * 5.0 ``` let’s assume we needed a **random odd number less than 100**, we could say: ```python r_odd = rng.randrange(1, 100, 2) ``` This example shows how to **shuffle a list**: ```python cards = list(range(52)) # Generate ints [0 .. 51] representing a pack of cards. rng.shuffle(cards) # Shuffle the pack ``` --- # The time Module ```python import time def do_my_sum(xs): sum = 0 for v in xs: sum += v return sum sz = 10000000 # Lets have 10 million elements in the list testdata = range(sz) t0 = time.time() my_result = do_my_sum(testdata) t1 = time.time() print(f"my_result = {my_result} (time taken = {t1-t0:.4f} seconds)") t2 = time.time() their_result = sum(testdata) t3 = time.time() print(f"their_result = {their_result} (time taken = {t3-t2:.4f} seconds)") ``` --- # The time Module (Contd.) On a reasonably modest laptop, we get these results: ```python my_sum = 49999995000000 (time taken = 1.5567 seconds) their_sum = 49999995000000 (time taken = 0.9897 seconds) ``` So our function runs about 57% slower than the built-in one. --- # The math Module (Contd.) Notice the difference between this module and our use of random: in random and turtle we create objects and we call methods on the object. This is because objects have state, every random number generator has a seed value that determines its next result. Mathematical functions are “pure” and don’t have any state — calculating the square root of 2.0 doesn’t depend on any kind of state or history about what happened in the past. So the functions are not methods of an object — they are simply functions that are grouped together in a module called math. --- # Namespaces and Scoping Variables are names (identifiers) that map to objects. A namespace is a dictionary of variable names (keys) and their corresponding objects (values). A Python statement can access variables in a local namespace and in the global namespace. If a local and a global variable have the same name, the local variable shadows the global variable. Each function has its own local namespace. Class methods follow the same scoping rule as ordinary functions. It assumes that any variable assigned a value in a function is local. Therefore, in order to assign a value to a global variable within a function, you must first use the global statement. The statement global VarName tells Python that VarName is a global variable. Python stops searching the local namespace for the variable. --- # Namespaces and Scoping (Contd.) For example, we define a variable Money in the global namespace. Within the function Money, we assign Money a value, therefore Python assumes Money as a local variable. However, we accessed the value of the local variable Money before setting it, so an UnboundLocalError is the result. Uncommenting the global statement fixes the problem. ```python Money = 2000 def AddMoney(): # Uncomment the following line to fix the code: # global Money Money = Money + 1 print (Money) AddMoney() print (Money) ``` --- # The globals() and locals() Functions − The globals() and locals() functions can be used to return the names in the global and local namespaces depending on the location from where they are called. If locals() is called from within a function, it will return all the names that can be accessed locally from that function. If globals() is called from within a function, it will return all the names that can be accessed globally from that function. The return type of both these functions is dictionary. Therefore, names can be extracted using the keys() function. --- # Packages in Python A package is a hierarchical file directory structure that defines a single Python application environment that consists of modules and subpackages and sub-subpackages, and so on. Consider a file Pots.py available in Phone directory. This file has following line of source code − ```python def Pots(): print("I'm Pots Phone") ``` Similar way, we have another two files having different functions with the same name as above − ``` Phone/Isdn.py file having function Isdn() Phone/G3.py file having function G3() ``` --- # Packages in Python (Contd.) Now, create one more file `__init__.py` in Phone directory − ``` Phone/__init__.py ``` To make all of your functions available when you've imported Phone, you need to put explicit import statements in `__init__.py` as follows − ```python from Pots import Pots from Isdn import Isdn from G3 import G3 ``` After you add these lines to `__init__.py`, you have all of these classes available when you import the Phone package. ```python # Now import your Phone Package. import Phone Phone.Pots() Phone.Isdn() Phone.G3() ``` --- # References * https://www.tutorialspoint.com/python/python_modules.htm * http://www.ict.ru.ac.za/Resources/cspw/thinkcspy3/thinkcspy3_latest/modules.html * https://docs.python.org/3/tutorial/modules.html --- class: center, middle .center[] # Thank you. Any questions?