### Lesson: Understanding and Creating Python Modules #### Introduction Python modules are a way to structure and organize your code by breaking it into smaller, manageable, and reusable components. This lesson covers how to create your own Python modules, the necessary directory structure, and the different ways to import them, including handling intra-module dependencies. --- #### Creating Your Own Python Module A Python module is simply a file containing Python definitions and statements. For example, a file named `mymodule.py` could be a module. **Example:** ```python # mymodule.py def greet(name): return f"Hello, {name}!" def add(a, b): return a + b ``` #### Directory Structure for Modules and Packages When your project grows, you might want to organize your modules into packages. A package is a directory containing a special `__init__.py` file and can contain multiple modules or sub-packages. **Example Directory Structure:** ``` my_project/ ├── main.py ├── mymodule.py └── mypackage/ ├── __init__.py ├── module1.py └── module2.py ``` The `__init__.py` file can be empty or can include package initialization code. It tells Python that the directory should be treated as a package. #### Importing Modules You can import modules and packages in several ways: 1. **Basic Import:** ```python import mymodule print(mymodule.greet("World")) ``` 2. **Import Specific Functions or Classes:** ```python from mymodule import greet print(greet("World")) ``` 3. **Import All Names from a Module:** ```python from mymodule import * print(greet("World")) ``` 4. **Aliasing Imports:** ```python import mymodule as mm print(mm.greet("World")) ``` #### Importing from Packages To import from packages, use the dot notation to specify the module within the package. **Example:** ```python # my_project/main.py from mypackage import module1 from mypackage.module2 import some_function print(module1.some_function()) print(some_function()) ``` #### Handling Intra-Module Dependencies When modules within the same package depend on each other, you can use relative imports. **Example:** ```python # my_project/mypackage/module1.py from .module2 import some_function def another_function(): return some_function() ``` Relative imports use a dot (.) to refer to the current package and double dots (..) to refer to the parent package. --- ### Cheat Sheet 1. **Creating a Module:** - Create a `.py` file with functions, classes, or variables. 2. **Creating a Package:** - Create a directory with an `__init__.py` file. - Add module files in the directory. 3. **Basic Import Syntax:** ```python import module_name from module_name import function_name from module_name import * import module_name as alias ``` 4. **Importing from Packages:** ```python from package_name import module_name from package_name.module_name import function_name ``` 5. **Relative Imports:** ```python from . import sibling_module from ..parent_package import module ``` --- ### Exercise: Real-World Example Create a small project with the following structure and implement the given requirements. **Project Structure:** ``` calculator/ ├── __init__.py ├── operations.py └── utils.py main.py ``` 1. **operations.py:** ```python from .utils import log_operation def add(a, b): result = a + b log_operation('add', a, b, result) return result def subtract(a, b): result = a - b log_operation('subtract', a, b, result) return result ``` 2. **utils.py:** ```python def log_operation(operation, a, b, result): print(f"{operation}({a}, {b}) = {result}") ``` 3. **main.py:** ```python from calculator.operations import add, subtract print(add(5, 3)) print(subtract(10, 4)) ``` **Steps:** 1. Create the directory structure. 2. Write the code for each file as shown. 3. Run `main.py` and verify the output. This exercise helps reinforce the concepts of module creation, importing, and handling intra-module dependencies.