Lists & Collections
What You'll Build Today
Welcome to Day 5! Today marks a massive shift in your ability to write useful software. Up until now, we have been dealing with single pieces of data: one number, one string of text, or one boolean flag.
But think about the real world. A chat history isn't one string; it's a sequence of twenty messages. A search result isn't one website; it's a collection of ten links. A dataset isn't one number; it's thousands of rows.
Today, we are building a Todo List Manager. While it sounds simple, this is the exact same logic used to manage conversation history in chatbots like ChatGPT.
Here is what you will master today:
* List Creation: How to create a single variable that holds thousands of items.
* Indexing and Slicing: How to pinpoint specific data (like the very first message) or grab a subset (like the last 3 messages for context).
* Methods (.append, .pop): How to dynamically grow and shrink your data as the program runs.
* List Comprehensions: A powerful, professional Python tool to filter and modify lists in a single line of code.
The Problem
Let's imagine you are trying to build a chatbot that remembers what the user said. Based on what you know so far, you might try to create a variable for every single message.
Look at this code. It is painful to write, and even more painful to read.
# The "Painful" Way to store history
msg_1 = "Hi, I am user 1."
msg_2 = "Hello user, how can I help?"
msg_3 = "I need to fix my python code."
msg_4 = "Sure, paste your code here."
msg_5 = "print('hello')"
# Now, imagine trying to search through these messages.
# You have to write an if-statement for EVERY variable.
search_term = "python"
if search_term in msg_1:
print("Found in message 1")
elif search_term in msg_2:
print("Found in message 2")
elif search_term in msg_3:
print("Found in message 3")
# ... we have to keep going forever.
Why is this broken?
msg_100 if you don't know yet if the user will type 100 things.msg_1 = msg_2, msg_2 = msg_3...).There has to be a container that can grow, shrink, and let us loop through everything at once. That container is a List.
Let's Build It
We are going to build a dynamic Todo List Manager. We will start small and add features step-by-step.
Step 1: Creating a List
A list in Python is defined by square brackets []. You can put anything inside it—strings, numbers, or even other lists.
# Creating a list with some initial data
tasks = ["Learn Python", "Build AI App", "Drink Coffee"]
print(tasks)
# We can also create an empty list to fill later
chat_history = []
print(chat_history)
Why this matters: You now have a single variable name (tasks) that represents a group of items. You can pass tasks around your program as one unit.
Step 2: Accessing Data (Indexing)
Python uses "zero-indexing." This means the first item in the list is at position 0, not 1. This is the most common mistake for beginners.
tasks = ["Learn Python", "Build AI App", "Drink Coffee"]
first_task = tasks[0] # This gets "Learn Python"
second_task = tasks[1] # This gets "Build AI App"
print("First thing to do:", first_task)
# You can also count from the end using negative numbers
last_task = tasks[-1] # This gets "Drink Coffee"
print("Last thing to do:", last_task)
Why this matters: When you build an AI chatbot, you often need to send the "system prompt" (the first instruction) or the "latest user query" (the last item). Indexing lets you grab exactly what you need.
Step 3: Slicing (The Context Window)
Sometimes you don't want just one item; you want a section. In AI, this is crucial for "Context Windows." You might only want to send the AI the last 5 messages so it doesn't get confused by old topics.
We use the syntax [start:end]. Note that it stops before the end number.
# Imagine a long conversation history
history = [
"Hi",
"Hello",
"Who are you?",
"I am a bot",
"Cool",
"Bye"
]
# Get the first 2 messages (0 up to, but not including, 2)
intro = history[0:2]
print("Intro:", intro)
# Get the last 3 messages
# If you leave the end blank, it goes to the very end
recent_context = history[-3:]
print("Recent Context:", recent_context)
Step 4: Adding and Removing Items
Lists are mutable (changeable). We can add new tasks and complete old ones.
* .append(item): Adds to the end.
* .remove(item): Finds the item and removes it.
* .pop(index): Removes the item at a specific index.
tasks = ["Learn Python", "Sleep"]
# 1. Add a new task
print("Adding task...")
tasks.append("Code Project")
print(tasks)
# 2. Remove a task by name
print("Removing Sleep...")
tasks.remove("Sleep")
print(tasks)
# 3. Remove the first task using pop
# .pop() also returns the item it deleted, in case you need it
print("Completing first task...")
completed_task = tasks.pop(0)
print(f"You completed: {completed_task}")
print(f"Remaining tasks: {tasks}")
Step 5: The "List Comprehension" (Filtering)
This is a slightly advanced concept, but it is standard practice in Python. A list comprehension allows you to create a new list based on an existing list in one line. It is incredibly useful for filtering data.
Imagine we want to find all tasks that contain the word "Code".
all_tasks = ["Code Python", "Wash dishes", "Code Project", "Walk dog"]
# The Syntax: [ item for item in list if condition ]
coding_tasks = [task for task in all_tasks if "Code" in task]
print("Original:", all_tasks)
print("Filtered:", coding_tasks)
Why this matters: In AI, you often need to filter "toxic" words out of a user's input or select only high-quality documents from search results. Comprehensions make this fast and readable.
Step 6: Putting it together (The Todo App)
Let's combine loops (from yesterday) with lists to make an interactive tool.
# Initialize empty list
todo_list = []
print("--- TODO MANAGER ---")
print("Commands: add, view, remove, quit")
while True:
action = input("\nWhat would you like to do? ").lower()
if action == "quit":
print("Goodbye!")
break
elif action == "add":
item = input("Enter task: ")
todo_list.append(item)
print(f"Added '{item}' to the list.")
elif action == "view":
print("\nYour List:")
# We use 'enumerate' to get the index numbers automatically
for index, task in enumerate(todo_list):
print(f"{index}. {task}")
elif action == "remove":
# First show the list so they know the numbers
print("\nYour List:")
for index, task in enumerate(todo_list):
print(f"{index}. {task}")
try:
num = int(input("Enter the number to remove: "))
removed = todo_list.pop(num)
print(f"Removed '{removed}'")
except:
print("Error: Invalid number.")
else:
print("I don't understand that command.")
Now You Try
You have a working Todo Manager. Now, extend its functionality to practice your new skills.
Add a command called clear. When the user types this, it should empty the entire list. (Hint: You can use the .clear() method, or simply re-assign the variable to an empty list []).
Right now, .append() adds to the bottom. Add a command called top that adds a task to the top (index 0) of the list. (Hint: Look up the .insert() method in Python documentation).
Add a command called sort. When typed, it should rearrange the tasks alphabetically. (Hint: Lists have a built-in .sort() method).
Challenge Project: The Toxic Content Filter
In GenAI development, "Safety Rails" are critical. You cannot pass user input directly to an LLM without checking it first, or the AI might be tricked into saying something offensive.
Your challenge is to build a content filter.
Requirements:user_messages containing 5-6 strings. Some should be normal, some should contain "banned" words (e.g., "spam", "virus", "attack").banned_words containing those specific bad words.user_messages.clean_messages.clean_messages list.Messages: ["Hello friend", "Click this spam link", "How are you?", "Download this virus"]
Banned: ["spam", "virus"]
["Hello friend", "How are you?"]
Hints:
* You will need a loop inside a loop. (For every message, check every banned word).
* Alternatively, you can use a boolean flag like is_clean = True before checking the banned words. If you find a banned word, set is_clean = False. Only append if is_clean is still True after checking.
What You Learned
Today you moved from managing single variables to managing collections of data.
* Lists []: The primary way to store sequences of data.
* Indexing [0]: How to retrieve specific items.
* Slicing [0:5]: How to grab context windows.
* Methods: .append(), .pop(), and .remove() give your program life and movement.
* Filtering: Using logic to separate good data from bad data.
Why This Matters for AI:Large Language Models (LLMs) are "stateless"—they don't remember you. When you chat with an AI, your code must send the entire list of previous messages (the history) along with your new question every single time. If you can't manage lists, you can't build a chatbot that remembers its own name.
Tomorrow:We have lists to store sequences, but what if we need to store structured data, like a user profile with a name, email, and ID? Lists are bad at that. Tomorrow, we learn Dictionaries—the key to organizing complex data.