The journey I embarked upon when I began learning Python- Day 2
Published: 2023-09-22 08:07:29

Today, I'm contemplating the idea of building a To Do List program, and I'm inclined to create a straightforward yet effective application to bring this concept to life.

**Requirement**
Develop a comprehensive to-do-list application that empowers users to effortlessly manage their tasks using Create, Read, Update, and Delete(CRUD) functionalities while seamlessly storing these tasks in a file for convenient access and organization.

**Clarify**
1. The program will encompass for distinct functions, each intricately tied to the Create, Read, Update, and Delete (CRUD) operations.
2. All tasks will be meticulously stored within a designed file, ensuring data preservation and easy retrieval.
3. User input will be actively solicited to provide the program with task details.
4. The program's output, including task management and updates, will be thoughtfully presented on the console for user convenience and clarity

**Coding**

```
# Define the file name where the to-do list will be stored
todo_list_file = 'todo_list.txt'

# Function to read tasks from the file
def read_tasks():
    try:
        with open(todo_list_file, 'r') as file:
            tasks = file.readlines()
            return tasks
    except FileNotFoundError:
        return []

# Function to write tasks to the file
def write_tasks(tasks):
    with open(todo_list_file, 'w') as file:
        for task in tasks:
            file.write(task + '\n')

# Function to display the to-do list
def display_tasks():
    tasks = read_tasks()

    if tasks:
        print('To-do List:')
        for i, task in enumerate(tasks, start=1):
            print(f'{i}. {task}')
    else:
        print("Your to-do list is empty.")

# Function to add a task
def add_task(task):
    tasks = read_tasks()
    tasks.append(task)
    write_tasks(tasks)

# Function to update a task
def update_task(index, new_task):
    tasks = read_tasks()
    if 0 < index <= len(tasks):
        tasks[index - 1] = new_task
        write_tasks(tasks)
        print(f'Task {index} updated.')
    else:
        print('Invalid task index.')

# Function to delete a task
def delete_task(index):
    tasks = read_tasks()
    if 0 < index <= len(tasks):
        deleted_task = tasks.pop(index - 1)
        write_tasks(deleted_task)
        print(f'Task {index} ({deleted_task}) deleted.')
    else:
        print('Invalid task index')

# Main function:

while True:
    print('\n Options:')
    print("1. View Tasks")
    print("2. Add Tasks")
    print("3. Update Task")
    print("4. Delete Task")
    print("5. Quit")

    choice = input("Enter your choice (1/2/3/4/5): ")

    if choice == "1":
        display_tasks()
    elif choice == "2":
        task = input("Enter the task: ")
        print(task)
        add_task(task)
    elif choice == "3":
        index = int(input("Enter the task index to Update: "))
        new_task = input("Enter the new task: ")
    elif choice == "4":
        index = int(input("Enter the task index to delete: "))
        delete_task(index)
    elif choice == "5":
        print("Exiting the program.")
    else:
        print("Invalid choise. Please choose 1, 2, 3, 4, or 5.")
```
Using the provided code, I will comprehensively elucidate the breadth of knowledge and skills I applied manage and navigate the program.

**1. File Handling (`read_tasks` and `write_tasks` functions)**

```
def read_tasks():
    try:
        with open(todo_list_file, "r") as file:
            tasks = file.readlines()
        return [task.strip() for task in tasks]
    except FileNotFoundError:
        return []

def write_tasks(tasks):
    with open(todo_list_file, "w") as file:
        for task in tasks:
            file.write(task + "\n")
```
* These functions are defined using the **`def`** keyword.
* **`try`** and **`except`** blocks are used for error handling.
* The **`with`** statement is used for file operations, ensuring that the file is properly closed when the block is exited.

**2. Basic Input and Output (`input` and  `print`)**

```
choice = input("Enter your choice (1/2/3/4/5): ")
print("To-Do List:")
```
* `input` is used to obtain user input.
* `print` is used to display messages and information to the user.

**3. Data Structures(Lists)**

```
tasks = []
```
* Lists are created and manipulated. **`tasks`** is a ; is a list used to store the to-do-list items.

**4. Functions (`add_task`, `update_task`, `delete_task`, `display_tasks`)**

```
def add_task(task):
    tasks.append(task)

def update_task(index, new_task):
    tasks[index - 1] = new_task

def delete_task(index):
    deleted_task = tasks.pop(index - 1)

def display_tasks():
    for i, task in enumerate(tasks, start=1):
        print(f"{i}. {task}")
```
* Function are defined using `def`.
* Parameters are passed within the parentheses.
* `enumerate` is used to iterate through tasks and get both the index and task.

**5. Conditional Statement (`if`, `elif`, `else`)**

```
if choice == "1":
    # View tasks
elif choice == "2":
    # Add task
else:
    # Handle invalid choice
```
* `if`, `elif` and `else` statements are used for conditional branching.

**6. Loops(`while True`)**

```
while True:
    # Main program loop
```

**7. Error Handling (`try` and `except`)**

```
try:
    # Attempt an operation
except FileNotFoundError:
    # Handle the specific exception
```
* Error Handling is implemented using `try` and `except` blocks

**8. String Manipulation**

```
print(f"{i}. {task}")

* F-strings (formatted strings) are used for string interpolation

```
**9. List Comprehension**
```
[task.strip() for task in tasks]
```

* List Comprehensive: `[..]` is a list comprehension, which is a concise way to create lists in Python
* Iteration `for task in tasks` iterates through each element (in this case, each task) in the `tasks` list.
* `task.strip()`: Within the list comprehension, `task.strip()` is applied to each `task` element. The `strip()` method is used to remove leading and trailing whitespace (spaces, tabs, newline characters, etc) from a string

**10. Modularity**

* Functions are used to encapsulate specific behaviors, promoting modularity and code reusability

**11. Application Logic:**
* The core logic of the program is implemented within function such as `add_task`, `update_task`, `delete_task` and `display_tasks`.

**12 Flow Control:**
* Flow control is achieved through loops (`while`) and condition statements (`if`, `elif`, `else`) to direct the program's execution flow.

**13. User experience Design**

* A simple text-based menu is created to facilitate user interaction with the program.

**14. File I/O Best Practices**

* The `with` statement is used for file operations, ensuring proper file handling.

These are the key insights and skills I've applied in managing the console-based to-do list program. My hope is that by sharing this experience, I t can serve as a valuable resource for others who, like me, are in the process of learning  and master these concepts.