Skip to content
20 min read

How to become a programmer

If you want to become a programmer, the first step is not choosing a framework, watching another course, or memorizing syntax.

Write a small program. Then run it. Then break it. Then figure out why it broke.

That loop is a better introduction to programming than collecting tutorials.

This guide gives you a progressive path from your first lines of code to several small projects. You will use Scratch to understand the basic idea of programming, Python to learn programming fundamentals, the terminal and Git as everyday tools, testing as part of writing reliable software, and AI as a mentor when you get stuck.

The goal is to start programming, understand what your code is doing, and gradually become someone who can solve problems with code.


What you are actually learning

The skill is turning a problem into a sequence of instructions a computer can run. That sequence is an algorithm. A language is how you write it. This guide uses Python.

You will practice that through increasingly useful projects.

Along the way, you will develop four habits:

  • Curiosity: ask why the program behaves the way it does.
  • Self-teaching: learn how to find the information you need.
  • Code reading: understand code you did not write.
  • Debugging: investigate why code does not behave as expected.

Later, you will add another habit:

  • Testing: verify that your code behaves as expected.

These skills matter beyond Python. Python is simply the tool we will use to practice them.


Before Python: understand what programming is

If you have never programmed before, start with Scratch.

You do not need to spend weeks there.

Two or three short sessions are enough.

Build something simple:

  • Make a character move.
  • Ask the user something.
  • Use an if condition.
  • Repeat an action with a loop.
  • Keep a score.

Scratch lets you see the basic idea of programming without worrying about Python syntax.

You are already programming when you tell a computer:

  1. Do this.
  2. Check this condition.
  3. Repeat this action.
  4. Store this value.
  5. Do something different depending on the result.

Python will express those same ideas using text.

That is why we move from Scratch to Python instead of staying there.


Why Python?

Python is a high-level programming language, meaning its syntax is relatively close to natural language, making code easier to read.

You can use Python for:

  • automation
  • scripts
  • APIs
  • backend development
  • data analysis
  • machine learning
  • robotics
  • command-line tools

Python lets you focus on programming concepts without immediately having to understand a large framework or low-level programming concepts such as memory and CPU management.

You will learn variables, types, conditions, loops, functions, lists, errors, files, and eventually databases.

These concepts will help you understand other programming languages later.

You do not need to learn several languages at the same time.

Stay with one language long enough to build things.


Your first week

Plan on 45-90 minutes a day.

You will get stuck, so read the error. That is part of the work.

Your first week has one goal:

Go from "I have never programmed", to "I can write, run, break and fix a small Python program."

Your tools

Install:

On macOS and Linux, use Terminal.

On Windows, PowerShell is enough.

You will also use an AI assistant as a mentor.

It can be ChatGPT, Claude, Gemini, or an assistant integrated into your editor.

How you use it matters more than which one you pick.

If you have never seen code, do two or three short sessions in Scratch, then come back to Python.

This week follows the early concepts on roadmap.sh/python: syntax, variables, control flow, functions, and lists.

Leave files, modules, and venv for later.

File names, variable names, and commands in this guide stay in English.

Write first. Ask for a hint only if you are stuck

  1. Write the exercise yourself and run it.
  2. If it works and you can explain it, do not open AI.
  3. If you are stuck after 20--30 minutes, ask for a hint, not the full file.
  4. Include the error, what you expected, and what actually happened.
  5. Type the change yourself.
  6. Explain the fix in your own words.

The goal is to learn how to solve problems, not how to ask AI for finished programs.

Load this into your AI session

Paste it once. Then start Day 1.

You are my Python mentor. I am a beginner.
I want to learn programming fundamentals, not just copy working code.

When I am stuck:

- Ask me what I expected to happen.
- Ask me what actually happened.
- Help me read the error.
- Give me a hint or a small next step.
- Do not give me the complete solution unless I explicitly ask for it.

When explaining something, distinguish between:

- Python syntax: how Python expresses an idea.
- Programming concepts: ideas that also exist in other languages.

Keep explanations short.

Ask me to explain the solution back in my own words.

Install Python

Go to python.org and install Python for your operating system.

After installation, open your terminal and check that Python works:

python --version

You should see a Python 3.x version.

If that command is not found, try python3 --version. Use whichever command printed a 3.x version for the rest of this guide. Windows often uses python; macOS and Linux often use python3.


The Python REPL

Python also gives you an interactive environment called the REPL.

REPL stands for Read-Eval-Print Loop.

It reads the code you enter, evaluates it, prints the result, and waits for the next instruction.

Start it with:

python

You should see something similar to:

>>>

The >>> is the REPL prompt. Anything you type after it is Python code. Try:

2 + 2

Python immediately evaluates the expression:

4

Try:

name = "Beginner"
print(name)

You can also experiment with variables:

score = 100
score + 50

The REPL is useful when you want to quickly experiment with Python without creating a file.

You can use it to try out functions too:

len("Python")
print("Hello, Python!")
numbers = [10, 20, 30]
sum(numbers)
sum(numbers) / len(numbers)

You can also make mistakes and see the error immediately:

10 / 0

Exit with:

exit()

The REPL is not where you will build your projects. It is a small laboratory where you can test ideas.

Python syntax and reserved words

Python has reserved words: words that already have a specific meaning in the language.

For example:

if
else
for
while
def
return
import

You cannot use these words freely as variable or function names because Python already uses them for its syntax.

You do not need to memorize all Python reserved words. You will learn them as you use them.

When you encounter syntax you do not understand, look it up.

W3Schools Python is useful for quick explanations, while the official Python tutorial is a deeper reference.


Day 1: run your first program

Start with something simple. You are going to create a directory, create a Python file inside it, open it in VS Code, and run it from the terminal.

This directory is the only project you will use in this guide. Later days add numbered folders next to 01-hello.

1. Create your project directory

Open your terminal:

mkdir -p how-to-become-a-programmer/01-hello

Move into the project:

cd how-to-become-a-programmer

Check where you are:

pwd

On Windows PowerShell, pwd and ls work as aliases. You can keep using them here.

List the files:

ls

You should see 01-hello. You will use these commands repeatedly:

  • mkdir: create a directory
  • cd: move between directories
  • pwd: show your current directory
  • ls: list files

You don't need to memorize them today. You will learn them by using them.

2. Open the project in VS Code

If the code command is available:

code .

The . means the current directory.

If the command is not available, open VS Code and select the how-to-become-a-programmer directory.

3. Create your first Python file

Inside 01-hello, create:

hello.py

The tree should look like this:

how-to-become-a-programmer/
└── 01-hello/
    └── hello.py

Add:

print("Hello, Beginner.")

Save the file.

4. Run the program

Go back to the terminal. Make sure you are still inside how-to-become-a-programmer:

pwd

Run:

python 01-hello/hello.py

You should see:

Hello, Beginner.

You just wrote and executed a program.

Exercise

Modify the program:

message = "Hello, Beginner."
print(message)

Change the message. Add another variable. Print another value. Run the program after every change.

The goal is to become comfortable with this cycle:

Edit
 ↓
Save
 ↓
Run
 ↓
Observe
 ↓
Change
 ↓
Run again

Now break it

Delete one of the quotation marks:

print("Hello, Beginner.)

Run it again. Python will show an error. Read it.

You do not need to understand every line yet. Find the important part and look at where Python thinks the problem happened.

Fix the quotation mark. Run it again.

You just found and fixed your first bug.

Programming involves reading what the computer tells you and using that information to find the problem.


Day 2: variables and input

Stay in how-to-become-a-programmer. Create a folder for the next exercises:

mkdir 02-python-basics

Create 02-python-basics/variables.py:

name = input("What is your name? ")
print("Hello,", name)

Run it:

python 02-python-basics/variables.py

If you type:

Beginner

you should get:

Hello, Beginner

There are already several concepts here.

name is a variable. input() gets information from the user. print() displays information.

A value has a type. input() always returns a string, even if you type a number. "18" is not the number 18.

Python executes the instructions in order. Try modifying the program:

name = input("What is your name? ")
age = input("How old are you? ")
print("Hello,", name)
print("You are", age, "years old.")

Then experiment. Ask yourself:

  • What happens if I create another variable?
  • What happens if I change the value?
  • What happens if I print a variable before assigning it?
  • What type of value does input() return?

You are learning by changing the program and observing what happens.


Day 3: decisions

Programs become useful when they can make decisions.

Create 02-python-basics/decisions.py:

age = int(input("How old are you? "))
if age >= 18:
    print("You are an adult.")
else:
    print("You are under 18.")

int() converts the string from input() so >= can compare numbers.

Run it:

python 02-python-basics/decisions.py

If a condition is true, execute one path. Otherwise, execute another.

Try changing the condition. Then write small programs yourself:

  1. Check whether a number is positive or negative.
  2. Check whether a number is even or odd.
  3. Compare two numbers.
  4. Ask for a password and check whether it is correct.

Write them yourself. If you get stuck, ask AI for a hint.


Day 4: loops, functions, and lists

Programs often need to repeat things. Create 02-python-basics/loops.py:

for number in range(1, 6):
    print(number)

Run it:

python 02-python-basics/loops.py

Then create a list in the same file:

names = ["Alice", "Bob", "Charlie"]
for name in names:
    print(name)

A list lets you keep multiple values together. A list is a data structure. Now put logic into a function:

def greet(name):
    print("Hello,", name)

greet("Alice")
greet("Bob")

These concepts are fundamental:

  • variables store values
  • conditions make decisions
  • loops repeat work
  • functions organize behavior
  • lists hold collections of values

Do not rush past them because they look simple. You will use them repeatedly.


Days 5–6: build a number guessing game

Now combine those pieces in one program: a number guessing game.

mkdir 03-number-guessing-game
how-to-become-a-programmer/
├── 01-hello/
│   └── hello.py
├── 02-python-basics/
│   ├── variables.py
│   ├── decisions.py
│   └── loops.py
└── 03-number-guessing-game/
    └── game.py

Create 03-number-guessing-game/game.py.

Step 1: generate a number

Start small:

import random

secret = random.randint(1, 100)
print(secret)

Run it:

python 03-number-guessing-game/game.py

You should see a number between 1 and 100. Make sure you understand what the program is doing. Then remove print(secret).

Step 2: ask for a guess

Add:

guess = int(input("Your guess: "))

Run the program again. If you enter:

50

guess contains the integer 50.

Step 3: compare the guess

Add:

if guess > secret:
    print("Too high.")
elif guess < secret:
    print("Too low.")
else:
    print("You got it!")

Run it several times.

Step 4: keep asking

Put the guessing code inside a loop:

while True:
    guess = int(input("Your guess: "))

    if guess > secret:
        print("Too high.")
    elif guess < secret:
        print("Too low.")
    else:
        print("You got it!")
        break

Run it. You now have the core game.

Step 5: put the game in a function

Move the code into a function:

import random

def play_game():
    secret = random.randint(1, 100)

    print("Guess the number between 1 and 100.")

    while True:
        guess = int(input("Your guess: "))

        if guess > secret:
            print("Too high.")
        elif guess < secret:
            print("Too low.")
        else:
            print("You got it!")
            break

if __name__ == "__main__":
    play_game()

This block runs when you execute the file. It does not run when another file imports it.

Run it:

python 03-number-guessing-game/game.py

Now break it

Delete the int():

guess = input("Your guess: ")

Enter:

50

Read the error. What type is guess now? Fix the program.

Your exercise

Add one feature at a time:

  • Count the number of attempts.
  • Limit the number of guesses.
  • Add difficulty levels.
  • Give the player a score.
  • Allow the player to play again.

Before adding a feature, write down what the program should do. Then change the smallest amount of code you can.

Run it. Test the new behavior.

If it breaks, read the error before searching for an answer. You now have a small program with requirements you can change.

Once the attempt counter works, try two ways of playing. Guess at random. Then guess by halving the range: 50, then 25 or 75, and so on. Halving finds any number from 1 to 100 in at most seven guesses. Random guessing does not. That method is binary search. You already have the tool to measure it: the attempt counter.


Day 7: Git and GitHub

You now have a guessing game. Save the whole workspace with Git.

What problem does Git solve?

Imagine working on a project for several weeks.

You change the code. Something breaks. You change it again. Now you cannot remember what worked before.

Git keeps a history of your project. Instead of creating files such as:

project-final.py
project-final-2.py
project-final-fixed.py
project-final-really-fixed.py

you keep one project and record meaningful changes in its history. Each commit is a checkpoint in that history. You can see what changed, when it changed, and why it changed. That becomes increasingly useful as projects grow.

Your first Git history

Stay in how-to-become-a-programmer. Create a .gitignore file so Git does not track generated files. .venv/ is listed now even though you will create it later:

.venv/
__pycache__/
*.pyc
*.sqlite

Create README.md:

Python exercises from the first program to small projects.

Initialize Git at the repo root:

git init

Tell Git who you are. Use the name and email you want on commits. GitHub can keep the email private.

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Git is now tracking the repository. Check the state:

git status

You should see your Python files as untracked files. Add them to the staging area:

git add .

Check the state again:

git status

The files are now staged. Create your first commit:

git commit -m "Add number guessing game and week 1 exercises"

The first commit includes 01-hello/, 02-python-basics/, and 03-number-guessing-game/. That game is the project you will publish.

The basic model is:

Working files
    ↓
git add
    ↓
Staged changes
    ↓
git commit
    ↓
Project history
    ↓
git push
    ↓
GitHub

Look at the history:

git log --oneline

You should see the commit you just created.

Make another change

Add an attempt counter to 03-number-guessing-game/game.py:

import random

def play_game():
    secret = random.randint(1, 100)
    attempts = 0

    print("Guess the number between 1 and 100.")

    while True:
        guess = int(input("Your guess: "))
        attempts += 1

        if guess > secret:
            print("Too high.")
        elif guess < secret:
            print("Too low.")
        else:
            print("You got it in", attempts, "attempts!")
            break

if __name__ == "__main__":
    play_game()

Run it:

python 03-number-guessing-game/game.py

Create another commit:

git add 03-number-guessing-game/game.py
git commit -m "Count attempts in the guessing game"

Look at the history again:

git log --oneline

Now you have two checkpoints.

Git records how your project changes over time.

GitHub

Git and GitHub are different things.

Git is the version control tool that runs on your computer. GitHub is a platform where Git repositories can be hosted and shared.

Create an empty repository on GitHub. Do not add a README yet. You already have one locally.

Before you push, GitHub needs to know it is you. Account passwords no longer work for Git over HTTPS.

Create a personal access token. When git push asks for a password, paste the token, not your GitHub password.

If you already have GitHub CLI installed, you can run gh auth login instead.

Connect your local repository:

git remote add origin https://github.com/YOUR_USER/how-to-become-a-programmer.git

Rename your branch:

git branch -M main

Push it:

git push -u origin main

Refresh the repository. Your guessing game is now online. That is the beginner project to show: a game you wrote, not a print statement.

Git after week 1

Git is used for much more than keeping a backup.

Developers use it to:

  • work on the same code with a team
  • create branches for new features
  • review changes before merging
  • investigate when a bug appeared
  • revert changes
  • understand how a project evolved
  • contribute to open-source projects

Git repositories can also connect to CI/CD pipelines, where changes can trigger automated tests, builds, and deployments.

You do not need to learn all of that today. For now, build one habit:

Make small changes and create commits that represent concrete progress.

Useful Git resources

You now have a guessing game and its history online.

First month: turn exercises into projects

The first week teaches you the basic programming building blocks.

The first month should teach you how to combine them into something you can use.

Do not immediately move to Django, React, Docker, Kubernetes, AWS, or machine learning.

Build another project.

Build a Hangman game

Your next project is Hangman. Same repo, new folder.

mkdir 04-hangman
how-to-become-a-programmer/
└── 04-hangman/
    └── game.py

Create 04-hangman/game.py.

The first version should be small enough to understand in one sitting. The program chooses a word, the player guesses letters, and the program shows the letters that have been guessed.

Here is your starting boilerplate:

import random

WORDS = ["python", "terminal", "programming", "debugging"]

def display_word(word, guessed_letters):
    result = []

    for letter in word:
        if letter in guessed_letters:
            result.append(letter)
        else:
            result.append("_")

    return " ".join(result)

def play_game():
    word = random.choice(WORDS)
    guessed_letters = set()

    while True:
        print(display_word(word, guessed_letters))

        guess = input("Guess a letter: ").lower()
        guessed_letters.add(guess)

        if all(letter in guessed_letters for letter in word):
            print("You won!")
            break

if __name__ == "__main__":
    play_game()

Run it:

python 04-hangman/game.py

Try guessing letters until you complete the word. Then read the code before changing it. Ask yourself:

  • Where is the word selected?
  • Where are guessed letters stored?
  • What does display_word() return?
  • What does the while loop do?
  • What does all() check?
  • Why is play_game() called at the bottom?

A set stores unique items. all(...) is true when every letter in the word is in guessed_letters.

You do not need to understand every line immediately. Look up the pieces you do not understand.

For example:

word = random.choice(WORDS)

random.choice() selects one item from the list.

And:

guessed_letters = set()

creates an empty set that can hold the letters the player has guessed.

The point of the boilerplate is to give you a working starting point, not to remove the problem-solving part.

Break the program

Try something deliberately. For example, change:

guessed_letters = set()

to:

guessed_letters = []

Run the program. Read the error. Figure out why the change matters. Then restore it.

Change, run, observe, read the error, and fix it. Same loop as Day 1.

A set and a list both hold collections. A set has .add. The list you just tried does not.

Working on new features

You have a working version. Now add requirements. Implement these features one at a time:

  1. Draw the hangman's body parts when the player makes a mistake.
  2. Keep a list of incorrect letters.
  3. Add a scoring system.
  4. Allow the player to play again.
  5. Validate the player's input.

Do not implement everything at once.

Pick one feature. Change the code. Run the game. Check the behavior. If something breaks, debug it. Then commit the change:

git add 04-hangman/game.py
git commit -m "Add incorrect letters"
git push

The same repo grows. Push when a version works. Move to the next feature.

First month checkpoint

At the end of the first month, you should be able to:

  • Write small Python programs without copying every line.
  • Explain variables, types, conditions, loops, functions, and lists.
  • Run Python programs from the terminal.
  • Use the Python REPL for quick experiments.
  • Understand basic Python syntax and recognize common reserved words.
  • Read basic Python errors.
  • Debug a small program.
  • Use Git to create a history of your changes.
  • Make meaningful commits.
  • Publish a project on GitHub.
  • Add a feature to an existing program.
  • Search documentation when you do not know something.
  • Read small pieces of code written by someone else.
  • Use AI for guidance without outsourcing the whole problem.

You do not need to know everything.

You should be able to take a small problem, break it into smaller pieces, write some code, run it, investigate what goes wrong, and improve it.


From one file to several files

Notice what changed during the first month. You started with one folder. The repo now looks like this:

how-to-become-a-programmer/
├── .gitignore
├── README.md
├── 01-hello/
│   └── hello.py
├── 02-python-basics/
│   ├── variables.py
│   ├── decisions.py
│   └── loops.py
├── 03-number-guessing-game/
│   └── game.py
└── 04-hangman/
    └── game.py

The language is still Python. What changes is the amount of work the program has to do and how you organize it.

Month 2: make your programs useful

Now build programs that solve small problems.

The projects are still small, but they should start looking more like tools you could use.

You will install pytest in this month. Create a virtual environment first so the install does not touch the system Python.

Set up a virtual environment

A virtual environment gives your project its own isolated Python packages. Create one at the repo root:

python -m venv .venv

Activate it.

macOS/Linux

source .venv/bin/activate

Windows

.venv\Scripts\activate

Your prompt may show (.venv). That means later pip and pytest commands use this interpreter.

Install pytest:

python -m pip install pytest

.venv/ is already in .gitignore from Day 7.

Different projects can depend on different versions of third-party packages. Keeping their dependencies isolated prevents them from interfering with each other.

File organizer

Write a script that decides where a file belongs, then test that decision.

mkdir 05-file-organizer
how-to-become-a-programmer/
└── 05-file-organizer/
    ├── organizer.py
    └── test_organizer.py

Start with get_category on two filenames: photo.jpg and report.pdf.

Write the tests first in 05-file-organizer/test_organizer.py:

from organizer import get_category

def test_image_category():
    assert get_category("photo.jpg") == "images"

def test_document_category():
    assert get_category("report.pdf") == "documents"

Then implement the function in 05-file-organizer/organizer.py:

def get_category(filename):
    if filename.endswith(".jpg"):
        return "images"
    if filename.endswith(".pdf"):
        return "documents"
    return "other"

if __name__ == "__main__":
    print(get_category("photo.jpg"))
    print(get_category("report.pdf"))

Run the tests from the repo root:

pytest 05-file-organizer/test_organizer.py

They should pass.

Ask yourself:

  • Why does from organizer import get_category work from the test file?
  • What happens with a filename that is neither .jpg nor .pdf?
  • Why is get_category a function instead of a script that moves files?

Break it on purpose. Change "images" to "pictures" and run pytest again. Read the failure. Restore it.

Then expand: more extensions, then moving files. You will learn about files and directories.

git add 05-file-organizer
git commit -m "Classify jpg and pdf files"
git push

Expense calculator

Create a folder with the CSV, the program, and the tests together:

mkdir 06-expense-calculator
how-to-become-a-programmer/
└── 06-expense-calculator/
    ├── calculator.py
    ├── expenses.csv
    └── test_calculator.py

06-expense-calculator/expenses.csv:

date,category,amount
2026-08-01,food,15.50
2026-08-02,transport,8.00
2026-08-03,food,22.00

Write the tests first in 06-expense-calculator/test_calculator.py:

from calculator import calculate_total, totals_by_category

def test_calculate_total():
    assert calculate_total([10, 20, 30]) == 60

def test_calculate_total_with_empty_list():
    assert calculate_total([]) == 0

def test_calculate_total_with_one_price():
    assert calculate_total([50]) == 50

def test_totals_by_category():
    rows = [
        {"category": "food", "amount": "15.50"},
        {"category": "transport", "amount": "8.00"},
        {"category": "food", "amount": "22.00"},
    ]
    totals = totals_by_category(rows)
    assert totals["food"] == 37.5
    assert totals["transport"] == 8.0

Then implement 06-expense-calculator/calculator.py:

import csv
import os

def calculate_total(prices):
    return sum(prices)

def totals_by_category(rows):
    totals = {}
    for row in rows:
        category = row["category"]
        amount = float(row["amount"])
        totals[category] = totals.get(category, 0) + amount
    return totals

def read_expenses(path):
    with open(path, newline="") as file:
        return list(csv.DictReader(file))

if __name__ == "__main__":
    path = os.path.join(os.path.dirname(__file__), "expenses.csv")
    rows = read_expenses(path)
    prices = [float(row["amount"]) for row in rows]
    print(calculate_total(prices))
    print(totals_by_category(rows))

Run the tests:

pytest 06-expense-calculator/test_calculator.py

Run the program from the repo root:

python 06-expense-calculator/calculator.py

You should see 45.5 and a dictionary with food and transport totals.

A list of numbers is enough for a total. A dict keyed by category is the shape totals_by_category needs.

The habit matters more than the framework:

  1. Decide what the behavior should be.
  2. Write a test for that behavior.
  3. Implement it.
  4. Run the test.
  5. Change the code.
  6. Run the test again.

This introduces the basic idea behind test-driven development without turning this guide into a TDD tutorial.

Now deliberately break calculate_total. Run pytest. Read the failure. Fix the implementation. Run the tests again. Testing and debugging now work together.

git add 06-expense-calculator
git commit -m "Calculate expense totals from CSV"
git push

Terminal todo list

mkdir 07-todo
how-to-become-a-programmer/
└── 07-todo/
    └── todo.py

Create 07-todo/todo.py. The first version lists tasks and saves them to a file so they survive between runs:

import os
import sys

TASKS_FILE = os.path.join(os.path.dirname(__file__), "tasks.txt")

def load_tasks():
    if not os.path.exists(TASKS_FILE):
        return []
    with open(TASKS_FILE) as file:
        return [line.rstrip("\n") for line in file]

def save_tasks(tasks):
    with open(TASKS_FILE, "w") as file:
        for task in tasks:
            file.write(task + "\n")

def list_tasks(tasks):
    if not tasks:
        print("No tasks.")
        return
    for index, task in enumerate(tasks, start=1):
        print(f"{index}. {task}")

def main():
    tasks = load_tasks()
    command = sys.argv[1] if len(sys.argv) > 1 else "list"

    if command == "list":
        list_tasks(tasks)
    elif command == "add":
        task = " ".join(sys.argv[2:])
        tasks.append(task)
        save_tasks(tasks)
        print("Added:", task)
    else:
        print("Usage: python todo.py [list|add <task>]")

if __name__ == "__main__":
    main()

Run it:

python 07-todo/todo.py add "Learn Python"
python 07-todo/todo.py list

You should see:

1. Learn Python

Run list again. The task is still there because it was written to tasks.txt.

Ask yourself:

  • Where does load_tasks look for the file?
  • What happens on the first run, before tasks.txt exists?
  • Why does add call save_tasks?

Break it: comment out save_tasks(tasks) and add a task. Restart the program. The task is gone. Restore the save.

A file is enough for this project. Month 3 stores structured data in SQLite instead.

Features to add one at a time:

  • Delete a task by number.
  • Mark a task as done.
  • Ignore empty add commands.
git add 07-todo
git commit -m "Save todo list to a file"
git push

Month 3: databases and data

Now you can combine several things you have learned: files, functions, tests, and a third-party library.

Store your data with SQLite

Build a small program that generates game scores and stores them in a SQLite database.

What is SQLite?

SQLite is a small database engine.

Unlike a database server such as PostgreSQL, SQLite stores the database in a file. For learning, this is useful because you can work with a real database without first configuring a database server.

Python already includes the sqlite3 module. You do not need to install SQLite as a Python package.

mkdir 08-score-analyzer
how-to-become-a-programmer/
└── 08-score-analyzer/
    ├── database.py
    ├── analysis.py
    └── test_analysis.py

database.py creates the table and inserts sample rows. .gitignore already ignores *.sqlite, so Git will not commit the database file. The program creates it when you run this script.

Because this script writes scores.sqlite next to the code, move into the folder first:

cd 08-score-analyzer

Create database.py:

import sqlite3

connection = sqlite3.connect("scores.sqlite")
cursor = connection.cursor()

cursor.execute("DROP TABLE IF EXISTS scores")
cursor.execute(
    """
    CREATE TABLE scores (
        id INTEGER PRIMARY KEY,
        player TEXT,
        score REAL,
        game TEXT,
        created_at TEXT
    )
    """
)

rows = [
    ("Alice", 820, "guessing", "2026-08-01"),
    ("Bob", 540, "guessing", "2026-08-01"),
    ("Charlie", 910, "hangman", "2026-08-02"),
    ("Alice", 760, "guessing", "2026-08-02"),
    ("Bob", 680, "hangman", "2026-08-03"),
]
cursor.executemany(
    "INSERT INTO scores (player, score, game, created_at) VALUES (?, ?, ?, ?)",
    rows,
)
connection.commit()
connection.close()
print("Saved 5 scores.")

Run it:

python database.py

You should see Saved 5 scores.

Programs often need to remember information after they stop running.

Analyze the data with pandas

Install pandas and matplotlib in the same .venv you created in month 2. From the repo root (run cd .. if you are still in 08-score-analyzer):

python -m pip install pandas matplotlib

Create 08-score-analyzer/analysis.py. It reads the table you just created:

import matplotlib.pyplot as plt
import pandas as pd
import sqlite3

def average_by_player(df):
    return df.groupby("player")["score"].mean()

if __name__ == "__main__":
    connection = sqlite3.connect("scores.sqlite")
    df = pd.read_sql_query(
        "SELECT player, score FROM scores",
        connection,
    )
    connection.close()

    print(df)
    print(df["score"].mean())
    print(df["score"].max())
    print(average_by_player(df))

    average_by_player(df).plot(kind="bar")
    plt.title("Average Score by Player")
    plt.xlabel("Player")
    plt.ylabel("Average Score")
    plt.tight_layout()
    plt.savefig("average_score_by_player.png")

Run it from 08-score-analyzer:

cd 08-score-analyzer
python analysis.py

You should see the table, a few numbers, and a new file average_score_by_player.png. plt.savefig writes that file. If you are on a desktop and want a window, you can also call plt.show().

This is deliberately later in the path. You did not need pandas to learn variables, loops, functions, or debugging. You learned pandas because you had scores to summarize, not because a roadmap listed it.

Test average_by_player, a function you wrote, not pandas internals. Create 08-score-analyzer/test_analysis.py:

import pandas as pd
from analysis import average_by_player

def test_average_by_player():
    df = pd.DataFrame(
        {
            "player": ["Alice", "Alice", "Bob"],
            "score": [100.0, 200.0, 50.0],
        }
    )
    result = average_by_player(df)
    assert result["Alice"] == 150.0
    assert result["Bob"] == 50.0

From 08-score-analyzer:

pytest test_analysis.py

The __main__ guard you saw on Day 6 is why importing analysis does not try to open the database and draw a chart.

cd ..
git add 08-score-analyzer
git commit -m "Store scores in SQLite and chart averages"
git push

Your first three months

Your progression now looks like this:

Scratch
  ↓
Understand programming concepts
  ↓
Python
  ↓
Install and run Python
  ↓
REPL
  ↓
Python syntax and reserved words
  ↓
Write and execute code
  ↓
Terminal
  ↓
Debugging
  ↓
Number guessing game
  ↓
Git + GitHub
  ↓
Publish your work
  ↓
Hangman
  ↓
Work on new features
  ↓
venv
  ↓
Testing + pytest
  ↓
Files + CSV
  ↓
Terminal applications
  ↓
SQLite
  ↓
pandas
  ↓
Data analysis

You started with print().

Three months later, you can build a program, debug it, add features, test its behavior, track its history with Git, store data, analyze it, and visualize the result.

Each new concept appeared because the project needed it.


What to study along the way

Use a small set of good references.

Python

Use the official Python tutorial as your primary reference.

Use W3Schools Python when you want a quick explanation or example.

Use Think Python when you want a book-style explanation of programming concepts.

Use Exercism Python for additional exercises.

Use Python Tutor when you want to see code execution step by step.

Testing

Use the pytest documentation once testing becomes part of your projects.

Start with:

  • test files
  • test functions
  • assert
  • running pytest
  • understanding test failures

Learn more when your projects require it.

Roadmap

Use roadmap.sh/python as a map, not as a checklist you must finish immediately.

A roadmap can tell you what exists. It cannot tell you what you personally need to learn today. Do not open every technology on the roadmap.

Follow the next useful concept.

Git

Use GitHub Skills for guided practice.

Use Pro Git when you want a deeper reference.

Community

When documentation and experimentation are not enough, ask other developers.

Python Discussions is a good place to learn how Python developers discuss problems.

Stack Overflow is useful when you learn how to ask a precise technical question.

The quality of the question matters. Explain:

  • What you tried.
  • What you expected.
  • What actually happened.
  • The relevant code.
  • The exact error.

What to do after three months

Look at what you can already build.

If you enjoy backend development, explore APIs and frameworks such as FastAPI, Flask, or later Django.

If you enjoy data, go deeper into pandas, NumPy, and data visualization.

If you enjoy automation, keep building scripts that solve problems you have.

If you are interested in machine learning, learn the Python and data fundamentals first and then explore tools such as scikit-learn.

You can also learn web development with HTML, CSS, and JavaScript.

Have enough fundamentals to know why you are picking the next tool.

When a program is slow, or a problem is "find this", "sort that", or "shortest path", that is the moment to study algorithms on purpose. When you need lookup by name, or unique items, study more data structures on purpose. Not in week 1, and not because a roadmap listed them.


Learn to read code you did not write

There is another skill you should develop as writing your own programs gets easier.

Learn to read code written by someone else. Open a small open-source Python project. Do not try to understand the entire repository. Find one function. Read it.

Ask:

  • What are its inputs?
  • What does it return?
  • What variables does it create?
  • What functions does it call?
  • What happens if something goes wrong?
  • Where are its tests?
  • What do those tests tell you about the expected behavior?

Then change something locally and run the program or its tests. You are moving from:

"I can write code."

to:

"I can understand code."


Programming is mostly learning how to learn

You will constantly encounter things you do not know. You will forget syntax. You will misunderstand an API. You will get an error you have never seen. The skill is knowing what to do next.

Try something, observe the result, read the error, search, form a hypothesis, change one thing, run it again, and test it.

AI can help inside this loop. Use AI to ask:

  • "What should I investigate?"
  • "What does this error mean?"
  • "What concept am I missing?"
  • "Can you give me a smaller example?"
  • "Can you review my approach without solving it?"
  • "What should I test?"

Then write the solution yourself.


The goal

You do not become a programmer when you finish a Python course.

Start small. Build something. Break it. Debug it. Test it. Add a feature. Save it with Git. Publish it. Then build something slightly harder.

Your first projects need to teach you something.

Tomorrow: open 03-number-guessing-game/game.py, add one feature, commit, and push.

Thanks for reading! I hope you’ve found it useful. If you have any questions, feel free to get in touch.

This one’s dedicated to my friend Elías :)