<jupyter_start><jupyter_text>---     Department of Data ScienceCourse: Tools and Techniques for Data Science---Instructor: <NAME>, Ph.D.     Lecture 2.15 (Part - I)  _Creating_Modules.ipynb_          Learning agenda of this notebookModular Programming is a design technique to break your code into different parts. These parts in which we are breaking code into are called modules.**PART - I**1. Create a Module of your own2. Use the newly created module in this notebook file3. How Python locates a module?4. Reloading a module**PART - II**1. What are Python packages?2. How to create a Python Package?3. How to import modules from the package?  1. Create a Module named _`mymodule`_- Create `mymodule.py` file as shown below in the current working directory, i.e., the directory in which this IPython Notebook file resides.   mymodule.py```AUTHOR = '<NAME>'BATCH = 2021def myfactorial(num):     code    def myindex(numbers, no):     codedef mysort(numbers, inplace=False):     code```  2. Use the Functions of `mymodule`<jupyter_code>import mymodule as mm
print(dir(mm))
mm.AUTHOR
mm.mysort
mm.__name__
mm.__cached__<jupyter_output><empty_output><jupyter_text>>- `.pyc` files are created by the Python interpreter when a `.py` file is imported. >- The `.pyc` file contain the **compiled bytecode** of the imported module, so that the "translation" from source code to bytecode (which only needs to be done once) can be skipped on subsequent imports to speed up startup.>- If the `.pyc` is older than the corresponding .py file, we do have to re-import it in our program.>- The `.pyc` file is still interpreted, however, cnce the `.pyc` file is generated, there is no need of `.py` file, unless you edit it.<jupyter_code>mm.__builtins__<jupyter_output><empty_output><jupyter_text>**Let us use the `factorial()` function**<jupyter_code>mm.myfactorial(5)<jupyter_output><empty_output><jupyter_text>**Let us use the `myindex()` function**<jupyter_code>list1=[44, 99, -65, 101, 27, 88]
mm.myindex(list1, 101)<jupyter_output><empty_output><jupyter_text>**Let us use the `mysort()` function. Remember the default inplace argument is False, so it does not modify the list that is passed rather returns a new sorted list**<jupyter_code>list1=[44, 99, -65, 101, 27, 88]

rv = mm.mysort(list1)
rv
list1<jupyter_output><empty_output><jupyter_text>**Let us use the `mysort()` function and pass `inplace` argument as True, so it sort the list that is passed and returns None**<jupyter_code>list1=[44, 99, -65, 101, 27, 88]
rv = mm.mysort(list1, inplace=True)
type(rv)
list1<jupyter_output><empty_output><jupyter_text>3. How Python Locates a module?Let us try to import a module named `arifmodule` that is located in the following directory```/Users/arif/Documents/0-DS-522/Demo-Files-Repo/Section-2-Basics-of-Python-Programming/Lec-2.15-Creating-Python-Modules-and-Packages/module-files/pathissue/```<jupyter_code>import arifmodule<jupyter_output><empty_output><jupyter_text>>- **First** Python Interpreter looks for the module in the current working directory, i.e., the directory from which the input script was run>- Let us see the contents of current working directory<jupyter_code>import os
os.listdir()<jupyter_output><empty_output><jupyter_text>**So in the current working directory, we do not have the module named `arifmodule`** >- **Second** Python Interpreter looks for the module in the list of built-in modules of Python standard library>- Let us see the list of all builtin modules<jupyter_code>print(dir(__builtins__))<jupyter_output><empty_output><jupyter_text>**So `arifmodule` is not in the list of `__builtins__`** >- **Third** If there is no built-in module of that name, Python looks into a list of directories defined in `sys.path` environment variable>- Let us see the directories mentioned in the `sys.path` environment variable<jupyter_code>import sys
sys.path<jupyter_output><empty_output><jupyter_text>**The module `arifmodule` is not in either of the above locations** >- Let us now add the path of the directory containing `arifmodule` in the `sys.path` environment variable<jupyter_code>import sys
sys.path.append('/Users/arif/Documents/0-DS-522/Demo-Files-Repo/Section-2-Basics-of-Python-Programming/Lec-2.15-Creating-Python-Modules-and-Packages/module-files/pathissue/')<jupyter_output><empty_output><jupyter_text>**Now let us try to import `arifmodule` again**<jupyter_code>import arifmodule<jupyter_output><empty_output><jupyter_text>**Success**  4. Reload a module- The Python interpreter imports a module only once during a session. This makes things more efficient. - Consider `demomodule.py` located in the same directory in which this .ipynb file is located.  demomodule.py```print("This is the demomodule having only one print statement. It is located in the same directory in which this .ipynb file is...")```<jupyter_code># import the module for the first time
import demomodule<jupyter_output><empty_output><jupyter_text>**Let us import this module again**<jupyter_code>import demomodule

# you can note that python imports the module only once<jupyter_output><empty_output><jupyter_text>**What if we have made some changes in this module and want to reload it, there are two ways to do that:**1. Restart the Interpreter2. Call the `imp.reload()` function<jupyter_code>import imp
imp.reload(demomodule)
import demomodule<jupyter_output><empty_output><jupyter_text>Bonus: `main()` Function in Python- In most programming languages, the `main()` function serves as a starting point for the execution of a program. It is executed automatically every time the program is run.- In Python, it is not necessary to define the `main()`, because the Python interpreter executes from the top of the script file unless a specific function is defined. - However, having a defined starting point for the execution of your Python program is useful to better understand how a Python program works.  The Python `__name__` Variable and Python Execution Modes- In Python, the `.py` file may be executed as a script or may be imported as a module in another script.- Python has a special built-in variable, called `__name__`, that helps us decide whether we want to run the script or we want to import the functions defined in the script    - When you run your script, the `__name__` variable equals `__main__`     - When you import the containing script, the `__name__` variable will contain the name of the script.- Consider the following file named `myscript.py`:    ```def myFunction():    print('The value of __name__ is ' + __name__)def main():    myFunction()if __name__ == '__main__':    main()```  Scenario 1: Execute `myscript.py` as a Python Script<jupyter_code>!cat myscript.py
%run myscript.py<jupyter_output><empty_output><jupyter_text>>**So it proves that when we run the `myscript.py` file as a script the `__name__` variable contains `__main__`, the condition evaluates to True and therefore `main()` function is called which further caled `myFunction()`, which executes the print statement.**  Scenario 2: Import `myscript.py` in another script as a Python Module<jupyter_code>!cat myscript.py
import myscript as ms<jupyter_output><empty_output><jupyter_text>>**So it proves that when we import the `myscript.py` file as a module the `__name__` variable DOES NOT contains `__main__`, the condition evaluates to False and therefore `main()` function is NOT called and therefore nothing is printed on screen.****Now since the `myscript.py` has been imported, so we can call its functions. Let us call `myFunction()`**<jupyter_code>ms.myFunction()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0946994607391819, 'fraction_numerical': 0.011705905563593319, 'mean_word_length': 5.477001703577513, 'pattern_counts': {'":': 0, '<': 75, '<?xml version=': 0, '>': 88, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '187770', 'license': 'BSL-1.0', 'n_tokens_mistral': 2347, 'n_tokens_neox': 2241, 'n_words': 912, 'path': 'data-science-master/Section-2-Basics-of-Python-Programming/Lec-2.15-Creating-Python-Modules-and-Packages/module-files/creating_module.ipynb', 'repo_name': 'Hamid-Ali-99/Python_Just_Python', 'size': '7618'}