### 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.