🐍

Python Cheat Sheet

Beginner basics — everything from your first print() to strings and f-strings. Copy-paste the examples and learn by doing.

Jump to: First programprint()VariablesData types InputType conversionMathStrings Slicingf-stringsString methods Comparisonif / elif / elseLogical ops While loopsFor loopsLists List methods2D listsTuples UnpackingDictionariesFunctions CommentsClassesConstructors InheritanceModulesPackagesRandom Format specifiersDefault args*args / **kwargs ScopeComprehensionsSets ExceptionsFilesmatch-caseDunder methods Installing librariesExcel automationMachine learning 🚀 Projects

Your first program

Save a file as app.py, then run it. Python runs your code line by line, from the top.

print("Hello, world!")
print("My name is Mosh")

print()

print("Hello")        # text (a "string")
print("*" * 10)        # ********** (repeat a string)
print("A", "B", "C")  # A B C   (multiple values)

Variables

A variable is a labelled box that stores a value in memory. = assigns a value.

price = 10          # create / set
price = 20          # reset to a new value
print(price)        # 20
📝 Naming: use lowercase, separate words with _ (e.g. first_name), and pick descriptive names. Python is case-sensitive (Priceprice).

Data types

TypeExampleWhat it is
intage = 20Whole number
floatrating = 4.9Number with a decimal
strname = "Mosh"Text (a string)
boolis_new = TrueTrue / False (capital T/F!)
name = "Mosh"
age = 20
is_new = True
print(type(age))   # <class 'int'> — check a type

Receiving input

input() shows a prompt and returns whatever the user types — always as a string.

name = input("What is your name? ")
print("Hi " + name)   # join strings with +

Type conversion

Because input() gives a string, convert it before doing math.

birth_year = input("Birth year: ")
age = 2026 - int(birth_year)  # int() turns "1982" into 1982
print(age)
FunctionConverts to
int(x)integer
float(x)decimal number
str(x)string
bool(x)True / False
⚠️ "1982" (string) is not the same as 1982 (number). Mixing them gives a TypeError — convert first.

Math operators

OpMeaningExample
+ - * /add, subtract, multiply, divide10 / 3 → 3.33
//integer (floor) division10 // 3 → 3
%remainder (modulus)10 % 3 → 1
**power2 ** 3 → 8

Strings

Use single or double quotes. Use the other kind when your text contains a quote.

a = 'Python'
b = "Python's course"     # ' inside, so use "
c = 'He said "hi"'          # " inside, so use '
msg = """Hi John,
Thanks for joining.
The Team"""                 # triple quotes = multi-line

Indexing & slicing

Characters are numbered from 0. Negative numbers count from the end.

course = "Python for Beginners"
course[0]      # 'P'  (first char)
course[-1]     # 's'  (last char)
course[0:3]    # 'Pyt' (index 0,1,2 — stop is excluded)
course[1:]     # 'ython for Beginners' (to the end)
course[:5]     # 'Pytho' (from the start)
course[:]      # a full copy of the string
🎓 The [start:stop] slice includes start, excludes stop. This shows up on a lot of Python tests!

Formatted strings (f-strings)

Prefix with f and drop variables into { } — much cleaner than joining with +.

first = "John"
last = "Smith"
msg = f"{first} [{last}] is a coder"
print(msg)   # John [Smith] is a coder

String methods

Methods belong to a value and are called with a dot: course.upper(). They return a new string (the original is unchanged).

course = "Python for Beginners"
len(course)              # 20  (length — a general function)
course.upper()           # 'PYTHON FOR BEGINNERS'
course.lower()           # 'python for beginners'
course.title()           # 'Python For Beginners'
course.strip()           # remove spaces at the ends
course.find("o")         # 4   (index of first match, -1 if none)
course.replace("Beginners", "Pros")
"Python" in course      # True  (does it contain this?)

Comparison operators

These compare two values and produce a boolean (True/False).

OpMeansExample
==equal totemp == 30
!=not equalname != "Mosh"
> >=greater / or equaltemp > 30
< <=less / or equalage <= 18
⚠️ == compares, = assigns. temp = 30 sets a value; temp == 30 asks a question.

if / elif / else

Run code only when a condition is true. The indented block belongs to the if. elif = "otherwise if", else = "otherwise".

temp = 35
if temp > 30:
    print("It's a hot day")
    print("Drink water")
elif temp < 10:
    print("It's a cold day")
else:
    print("It's a lovely day")
# Example: down payment depends on credit
price = 1_000_000
has_good_credit = True
if has_good_credit:
    down = 0.1 * price          # 10%
else:
    down = 0.2 * price          # 20%
print(f"Down payment: ${down}")

Logical operators

Combine conditions: and (both true), or (at least one true), not (flips True↔False).

if has_high_income and has_good_credit:
    print("Eligible for a loan")      # both must be True

if has_high_income or has_good_credit:
    print("Eligible")               # at least one True

if has_good_credit and not has_criminal_record:
    print("Eligible")               # not False -> True

While loops

Repeat a block while a condition stays true. Always change something inside, or you get an infinite loop.

i = 1
while i <= 5:
    print(i)
    i += 1          # same as i = i + 1
print("Done")         # 1 2 3 4 5 Done

break jumps out of a loop early. A while … else runs the else only if the loop finished without a break:

secret = 9
guess_count = 0
guess_limit = 3
while guess_count < guess_limit:
    guess = int(input("Guess: "))
    guess_count += 1
    if guess == secret:
        print("You won!")
        break
else:
    print("Sorry, you failed")

For loops & range()

A for loop goes through each item in a collection (a string, a list, a range…).

for letter in "Python":
    print(letter)      # P y t h o n (each on a line)

for name in ["Mosh", "John", "Sarah"]:
    print(name)

for i in range(5):      # 0 1 2 3 4 (stop excluded)
    print(i)
range()Produces
range(5)0, 1, 2, 3, 4
range(5, 10)5, 6, 7, 8, 9
range(5, 10, 2)5, 7, 9 (step of 2)

Lists

A list holds many values in [ ]. Loop over it to process every item.

prices = [10, 20, 30]
total = 0
for price in prices:
    total += price
print(total)        # 60

Find the largest number

numbers = [3, 6, 2, 8, 4, 10]
max = numbers[0]
for n in numbers:
    if n > max:
        max = n
print(max)        # 10

List methods

Operations you can do on a list (call them with a dot):

numbers = [5, 2, 1, 7, 4]
numbers.append(20)        # add to the end
numbers.insert(0, 10)     # add at an index
numbers.remove(5)         # remove a value
numbers.pop()              # remove the last item
numbers.clear()           # remove everything
numbers.index(7)          # position of a value (error if missing)
7 in numbers              # True/False — safer existence check
numbers.count(5)          # how many times 5 appears
numbers.sort()            # sort ascending (in place)
numbers.reverse()         # reverse the order
copy = numbers.copy()     # an independent copy

Remove duplicates

numbers = [2, 2, 4, 6, 6, 3, 1]
uniques = []
for n in numbers:
    if n not in uniques:
        uniques.append(n)
print(uniques)     # [2, 4, 6, 3, 1]

2D lists (a list of lists)

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]
matrix[0][1]            # 2  (row 0, column 1)
matrix[0][1] = 20       # change a cell
for row in matrix:      # nested loops
    for item in row:
        print(item)

Tuples

Like a list, but immutable — you can't add, remove or change items. Use ( ).

point = (1, 2, 3)
point[0]            # 1  (reading is fine)
point[0] = 10       # ❌ TypeError — tuples can't change
# only .count() and .index() are available

Unpacking

Assign several variables from a list/tuple in one line.

coordinates = (1, 2, 3)
x, y, z = coordinates    # x=1, y=2, z=3
print(x, y, z)

Dictionaries

Store key → value pairs in { }. Keys must be unique.

customer = {
    "name": "John Smith",
    "age": 30,
    "is_verified": True,
}
customer["name"]                 # 'John Smith'
customer.get("birthdate")         # None if missing (no error)
customer.get("birthdate", "N/A")  # a default value
customer["name"] = "Jack"        # update
customer["phone"] = "1234"        # add a new pair
💡 dict[key] errors if the key is missing; dict.get(key, default) is safer. "good morning :)".split(" ") turns a string into a list of words — handy with dictionaries (emoji converters, phone-number spellers, etc.).

Functions

Group reusable code with def. Define before you call. Parameters are the placeholders; arguments are the values you pass.

def greet_user(first_name, last_name):
    print(f"Hi {first_name} {last_name}")
    print("Welcome aboard")

greet_user("John", "Smith")              # positional args
greet_user(last_name="Smith", first_name="John")  # keyword args (order-free)

Return a value

Use return to send a result back. A function with no return gives None.

def square(number):
    return number * number

result = square(3)
print(result)      # 9
📌 Rules: keyword arguments must come after positional ones. Add two blank lines after a function (PEP 8 style). Use descriptive names like calculate_cost.

Comments

Lines starting with # are ignored by Python. Use them to explain why (not what) — and don't overdo it.

# Tax rate assumed at 10% for 2026
price = 100  # base price before tax

Classes & objects

A class defines a new type (a blueprint). An object is an instance of it. Class names use PascalCase. Every method's first parameter is self (the current object).

class Point:
    def move(self):
        print("move")
    def draw(self):
        print("draw")

point1 = Point()        # create an object (instance)
point1.draw()           # call a method
point1.x = 10          # attributes = data on the object
print(point1.x)        # 10

Constructors (__init__)

__init__ runs automatically when you create an object — use it to set up (initialize) attributes so they always exist.

class Person:
    def __init__(self, name):
        self.name = name           # self = this object
    def talk(self):
        print(f"Hi, I am {self.name}")

john = Person("John Smith")     # name is passed to __init__
john.talk()                    # Hi, I am John Smith

Inheritance

A class can reuse another class's methods by inheriting from it — avoids repeating code (DRY). Use pass for an empty body.

class Mammal:
    def walk(self):
        print("walk")

class Dog(Mammal):     # Dog inherits walk()
    def bark(self):
        print("bark")

class Cat(Mammal):     # Cat inherits walk() too
    pass

dog1 = Dog()
dog1.walk()              # inherited
dog1.bark()              # Dog's own method

Modules

A module is just a .py file. Split related functions/classes into modules, then import them.

# converters.py has kg_to_lbs()
import converters
converters.kg_to_lbs(70)

# or import just what you need:
from converters import kg_to_lbs
kg_to_lbs(70)          # no prefix needed

Packages

A package is a folder of modules (it contains an __init__.py file). Import using dots.

# ecommerce/shipping.py has calculate_shipping()
import ecommerce.shipping
ecommerce.shipping.calculate_shipping()

from ecommerce.shipping import calculate_shipping
from ecommerce import shipping   # import the whole module

Random values (a built-in module)

Python ships with a big standard library. random is one example — no install needed.

import random
random.random()             # a float 0.0–1.0
random.randint(1, 6)         # whole number 1–6 (like a die)
random.choice(["Jon", "Mary", "Bob"])  # pick a random item
# Dice class that rolls two dice -> a tuple
import random
class Dice:
    def roll(self):
        return random.randint(1, 6), random.randint(1, 6)

dice = Dice()
print(dice.roll())      # e.g. (3, 5)

Format specifiers (pretty f-strings)

Inside an f-string, add : and a format spec to control how a value looks.

pi = 3.14159
name = "Mosh"
f"{pi:.2f}"          # '3.14'   (2 decimal places)
f"{1000000:,}"      # '1,000,000'  (thousands commas)
f"{0.25:.0%}"       # '25%'    (percent)
f"{name:>10}"       # right-align in 10 spaces
f"{name:^10}"       # center-align

Default & keyword arguments

Give a parameter a default so callers can skip it. Pass by name for clarity.

def greet(name, greeting="Hello"):   # greeting has a default
    print(f"{greeting}, {name}")

greet("Mosh")                 # Hello, Mosh
greet("Mosh", "Hi")           # Hi, Mosh
greet(greeting="Hey", name="Bob")  # keyword args (any order)

*args & **kwargs (any number of arguments)

def add(*numbers):       # *args  -> a tuple of all positional args
    return sum(numbers)
add(1, 2, 3, 4)          # 10

def profile(**info):     # **kwargs -> a dict of keyword args
    print(info)
profile(name="Mosh", age=30)  # {'name': 'Mosh', 'age': 30}

Variable scope

Variables made inside a function are local (gone when it ends). Use global to change a top-level variable from inside a function.

total = 0              # global
def add():
    global total      # without this you'd make a NEW local 'total'
    total += 1

List comprehensions

A short way to build a list from another sequence — one line instead of a loop.

nums = [1, 2, 3, 4, 5]
squares = [n * n for n in nums]            # [1, 4, 9, 16, 25]
evens = [n for n in nums if n % 2 == 0]    # [2, 4]

Sets

An unordered collection of unique items, in { }. Great for removing duplicates.

s = {1, 2, 3, 3, 2}       # {1, 2, 3}  (dupes dropped)
s.add(4)
{1, 2, 3} & {2, 3, 4}     # {2, 3}     intersection
{1, 2} | {3, 4}        # {1,2,3,4}  union
{1, 2, 3} - {2}        # {1, 3}     difference
set([1, 1, 2])           # {1, 2}  remove duplicates from a list

Exception handling (try / except)

Catch errors so your program doesn't crash. else runs if there was no error; finally always runs.

try:
    age = int(input("Age: "))
    print(100 / age)
except ValueError:
    print("Please enter a number")
except ZeroDivisionError:
    print("Age can't be zero")
else:
    print("No errors!")
finally:
    print("Done")             # always runs

File handling

Use with open(...) — it closes the file for you. Modes: "r" read, "w" write (overwrites), "a" append.

with open("notes.txt", "w") as f:
    f.write("Hello\n")
    f.write("Second line\n")

with open("notes.txt", "r") as f:
    content = f.read()        # whole file as one string
    # for line in f:  print(line)   # or line by line

match-case (Python 3.10+)

A clean alternative to a long if / elif chain.

command = "start"
match command:
    case "start":
        print("Starting…")
    case "stop":
        print("Stopping…")
    case _:                # _ = anything else (default)
        print("Unknown command")

Magic / dunder methods

Special methods named with double underscores let your objects work with built-in syntax (printing, ==, etc.).

class Point:
    def __init__(self, x):
        self.x = x
    def __str__(self):           # controls print(p)
        return f"Point({self.x})"
    def __eq__(self, other):      # controls p1 == p2
        return self.x == other.x

p = Point(5)
print(p)               # Point(5)
print(p == Point(5))    # True

Installing third-party libraries

Beyond the standard library, install packages from PyPI with pip (run in your terminal, not in Python).

pip install openpyxl
pip install pandas scikit-learn jupyter
💡 For data/ML work, Anaconda bundles Python + Jupyter + pandas/numpy/scikit-learn so you don't install them one by one. You write ML code in a Jupyter Notebook (cells you run one at a time) — great for inspecting data.

Project: automate Excel (openpyxl)

Read a spreadsheet, change values, and save — perfect for boring repetitive tasks across thousands of files.

import openpyxl as xl
from openpyxl.chart import BarChart, Reference

wb = xl.load_workbook("transactions.xlsx")
sheet = wb.active                 # or wb["Sheet1"]

cell = sheet.cell(1, 1)          # row 1, col 1  (or sheet["a1"])
print(cell.value)

for row in range(2, sheet.max_row + 1):   # skip header row 1
    price = sheet.cell(row, 3).value
    corrected = price * 0.9           # 10% off
    sheet.cell(row, 4).value = corrected  # write into a new column

wb.save("transactions2.xlsx")

Add a chart

values = Reference(sheet, min_row=2, max_row=sheet.max_row, min_col=4, max_col=4)
chart = BarChart()
chart.add_data(values)
sheet.add_chart(chart, "e2")        # top-left corner of the chart
🧹 Pro tip from the course: wrap it in a process_workbook(filename) function, then loop over every file in a folder to update thousands of spreadsheets in seconds.

Project: machine learning (pandas + scikit-learn)

The ML workflow: import → prepare → train → predict. Example: predict the music genre someone likes from their age & gender.

import pandas as pd
from sklearn.tree import DecisionTreeClassifier

# 1. import data (a CSV -> a DataFrame, like a spreadsheet)
music = pd.read_csv("music.csv")
music.shape          # (rows, columns)
music.describe()     # quick stats per column

# 2. prepare: split into input (X) and output (y)
X = music.drop(columns=["genre"])   # everything except the answer
y = music["genre"]                  # the answer column

# 3. build & train a model
model = DecisionTreeClassifier()
model.fit(X, y)

# 4. predict (21-yr-old male, 22-yr-old female)
predictions = model.predict([[21, 1], [22, 0]])
print(predictions)   # e.g. ['HipHop' 'Dance']
📊 Common ML libraries: pandas (data frames), numpy (arrays), matplotlib (plots), scikit-learn (algorithms like decision trees). Always split data into a training set and a testing set, then measure your model's accuracy.

🚀 Projects — build real things

Classic beginner-to-advanced projects (the ones from the big YouTube project courses), rewritten clean. One project of each level is free; reveal the rest with ⭐ credits, or unlock the whole Projects section.

Number Guessing Game EASY

Build: the computer picks 1–100; you guess until you get it, with hot/cold hints.

import random

secret = random.randint(1, 100)
guesses = 0
print("I'm thinking of a number between 1 and 100.")

while True:
    guess = int(input("Your guess: "))
    guesses += 1
    if guess < secret:
        print("Too low!")
    elif guess > secret:
        print("Too high!")
    else:
        print(f"You got it in {guesses} guesses!")
        break

Rock Paper Scissors EASY

Build: play against the computer; a dict decides who beats whom.

import random

options = ["rock", "paper", "scissors"]
beats = {"rock": "scissors", "paper": "rock", "scissors": "paper"}

you = input("rock, paper or scissors? ").lower()
cpu = random.choice(options)
print(f"Computer chose {cpu}.")

if you == cpu:
    print("Tie!")
elif beats.get(you) == cpu:
    print("You win!")
else:
    print("You lose!")

Password Generator EASY

Build: a random strong password of any length from letters, digits and symbols.

import random, string

length = int(input("Password length: "))
chars = string.ascii_letters + string.digits + "!@#$%^&*"
password = "".join(random.choice(chars) for _ in range(length))
print("Your password:", password)

Mad Libs EASY

Build: collect random words from the user, then drop them into a story.

Dice Roller EASY

Build: roll two dice on demand; doubles let you roll again.

Temperature Converter EASY

Build: convert between Celsius and Fahrenheit.

Calculator EASY

Build: a four-function calculator with divide-by-zero handling.

Countdown Timer EASY

Build: a ticking MM:SS countdown to zero.

Currency Converter EASY

Build: convert between currencies using a rate table (convert via USD).

Turtle Spiral (graphics) EASY

Build: a colourful spiral with Python's turtle. Opens a drawing window — won't run in the browser.

Weight Converter EASY

Build: convert between kilograms and pounds.

Stopwatch EASY

Build: start, then stop — and see how much time passed.

Tip Calculator & Bill Splitter EASY

Build: enter the bill, tip % and group size — get the tip, total, and each person's share.

BMI Calculator EASY

Build: weight + height in, BMI + category out — a first taste of if/elif chains.

FizzBuzz EASY

Build: the classic warm-up: multiples of 3 say Fizz, of 5 say Buzz, of both say FizzBuzz.

Palindrome Checker EASY

Build: ignores spaces, punctuation and case — 'A man, a plan, a canal: Panama' passes.

Multiplication Table EASY

Build: print a neat, right-aligned times table for any number.

Leap Year Checker EASY

Build: the real rule (divisible by 4, except centuries unless divisible by 400).

Days Until Your Birthday EASY

Build: enter your birthday as MM-DD and count down to it with the datetime module.

Acronym Generator EASY

Build: turn any phrase into its initials — 'random access memory' becomes RAM.

Word & Character Counter EASY

Build: instant text stats: words, characters, letters and the longest word.

Coin Flip Simulator EASY

Build: flip 1000 virtual coins, then report the totals and the longest streak.

Roman Numeral Converter EASY

Build: convert 1994 to MCMXCIV — then convert it right back to prove it works.

Decimal ↔ Binary Converter EASY

Build: see the same number in binary, octal and hex — then decode a binary string back.

Loan Payment Calculator EASY

Build: the real amortization formula banks use — see the true cost of a mortgage.

GPA Calculator EASY

Build: type letter grades until you press Enter on a blank line — get your GPA.

12-Hour ↔ 24-Hour Time Converter EASY

Build: type 14:30 to get 2:30 PM, or 2:30 PM to get 14:30 — strptime does the parsing.

Anagram Checker EASY

Build: do two words use exactly the same letters? sorted() makes it a one-liner.

Dice Statistics EASY

Build: roll two dice 10,000 times and draw a text histogram — watch the bell curve appear.

Piggy Bank EASY

Build: a tiny savings tracker: add money, check the balance, quit when you're done.

Hangman MEDIUM

Build: guess the hidden word letter by letter before you run out of lives.

import random

words = ["python", "rocket", "galaxy", "wizard", "dragon"]
word = random.choice(words)
guessed = set()
lives = 6

while lives > 0:
    shown = "".join(c if c in guessed else "_" for c in word)
    print(shown, f"  (lives: {lives})")
    if "_" not in shown:
        print("You won!")
        break
    letter = input("Guess a letter: ").lower()
    if letter in word:
        guessed.add(letter)
    else:
        lives -= 1
        print("Nope!")
else:
    print(f"Game over — the word was '{word}'.")

Quiz Game MEDIUM

Build: ask a list of questions, score the answers, show the result.

questions = [
    ("What keyword defines a function? ", "def"),
    ("What type is 3.14? ", "float"),
    ("What does len() return? ", "length"),
]
score = 0
for question, answer in questions:
    if input(question).strip().lower() == answer:
        print("Correct!")
        score += 1
    else:
        print(f"Wrong — it's '{answer}'.")
print(f"You scored {score}/{len(questions)}.")

Tic-Tac-Toe (2 players) MEDIUM

Build: a 3×3 board, alternating X/O, with win detection.

board = [" "] * 9
LINES = [(0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6)]

def show():
    for r in range(0, 9, 3):
        print(" " + " | ".join(board[r:r+3]))

def winner():
    for a, b, c in LINES:
        if board[a] == board[b] == board[c] != " ":
            return board[a]
    return None

player = "X"
for _ in range(9):
    show()
    i = int(input(f"{player}, pick 0-8: "))
    if board[i] == " ":
        board[i] = player
        if winner():
            show(); print(f"{player} wins!"); break
        player = "O" if player == "X" else "X"
else:
    print("It's a draw!")

Slot Machine MEDIUM

Build: a betting slot machine — match symbols to win, lose your bet otherwise.

Caesar Cipher (encryption) MEDIUM

Build: shift each letter to encrypt a message — and shift back to decrypt.

To-Do List (saved to a file) MEDIUM

Build: add/complete/list tasks that persist to a JSON file between runs.

The Computer Guesses Your Number MEDIUM

Build: you think of a number; the computer finds it with binary search.

Binary Search MEDIUM

Build: the classic O(log n) search — halve the range each step.

Alarm Clock MEDIUM

Build: wait until a set time, then sound the alarm.

Password Manager MEDIUM

Build: save and look up site passwords in a file (lightly scrambled).

Email Sender MEDIUM

Build: send an email from a script with smtplib (use a Gmail App Password).

Digital Clock (tkinter GUI) MEDIUM

Build: a live ticking clock in a window with tkinter. Opens a window — won't run in the browser.

Paint App (tkinter GUI) MEDIUM

Build: drag the mouse to draw on a canvas. Opens a window — won't run in the browser.

Typing Speed Test MEDIUM

Build: time how fast the user types a sentence and report words-per-minute.

Shopping Cart MEDIUM

Build: add items with prices, then print an itemised receipt with the total.

Contact Book (saved to JSON) MEDIUM

Build: add, list, search and delete contacts — everything persists to contacts.json between runs.

Expense Tracker (CSV + summary) MEDIUM

Build: log expenses by category to a CSV file, then get a per-category spending summary.

Flashcards Quiz MEDIUM

Build: a study tool: it asks, you answer, it scores you — swap in your own deck.

Vigenère Cipher MEDIUM

Build: the famous 'unbreakable' cipher of the 1500s — each letter shifts by a repeating keyword.

Morse Code Translator MEDIUM

Build: text to beeps and back — one dict powers both directions.

File Organizer MEDIUM

Build: the classic automation win: sweep a messy folder into Images/, Documents/, Music/… by extension.

Bulk File Renamer MEDIUM

Build: rename a whole folder of files to a clean numbered pattern like photo_001.jpg.

HTML Link Extractor MEDIUM

Build: parse real HTML with the standard library's html.parser — the first step to web scraping.

Markdown → HTML Converter MEDIUM

Build: a mini static-site engine: headers, bold, italic, code and lists become real HTML.

Rock Paper Scissors vs a Learning AI MEDIUM

Build: this opponent tracks your habits and counters your favourite move — beat it if you can.

Any-Base Number Converter MEDIUM

Build: convert between ANY two bases from 2 to 36 — hex, binary, base-7, you name it.

Blackjack (21) MEDIUM

Build: hit or stand against a dealer that must draw to 17 — with proper ace handling.

Wordle Clone MEDIUM

Build: 6 tries to guess a 5-letter word — 🟩 right spot, 🟨 wrong spot, ⬛ not in the word.

Multi-Unit Converter MEDIUM

Build: one converter for length, weight and temperature — dicts of factors do the math.

Pomodoro Timer MEDIUM

Build: the focus technique: work sprints and short breaks, with a live countdown in the terminal.

Tic-Tac-Toe AI (unbeatable, minimax) HARD

Build: an AI that never loses — it searches every future game with the minimax algorithm.

import math

board = [" "] * 9
LINES = [(0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6)]

def winner(b):
    for a, c, d in LINES:
        if b[a] == b[c] == b[d] != " ":
            return b[a]
    return None

def minimax(b, ai_turn):
    w = winner(b)
    if w == "O": return 1
    if w == "X": return -1
    if " " not in b: return 0
    scores = []
    for i in range(9):
        if b[i] == " ":
            b[i] = "O" if ai_turn else "X"
            scores.append(minimax(b, not ai_turn))
            b[i] = " "
    return max(scores) if ai_turn else min(scores)

def best_move(b):
    best, move = -math.inf, 0
    for i in range(9):
        if b[i] == " ":
            b[i] = "O"
            s = minimax(b, False)
            b[i] = " "
            if s > best:
                best, move = s, i
    return move

while winner(board) is None and " " in board:
    board[int(input("Your move 0-8: "))] = "X"
    if winner(board) is None and " " in board:
        board[best_move(board)] = "O"
    print(board[0:3], board[3:6], board[6:9])
print("Winner:", winner(board) or "Draw")

Bank Account System (OOP) HARD

Build: a class that guards its balance — deposits/withdrawals go through methods (encapsulation).

class Account:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("Deposit must be positive")
        self.balance += amount
        return self.balance

    def withdraw(self, amount):
        if amount > self.balance:
            print("Insufficient funds")
            return self.balance
        self.balance -= amount
        return self.balance

    def __str__(self):
        return f"{self.owner}: ${self.balance:.2f}"

acc = Account("Ada", 100)
acc.deposit(50)
acc.withdraw(30)
print(acc)   # Ada: $120.00

Markov Text Generator HARD

Build: learn which words follow which, then babble a new sentence in the same style.

import random

text = "the cat sat on the mat the cat ran to the hat"
words = text.split()

chain = {}
for current, nxt in zip(words, words[1:]):
    chain.setdefault(current, []).append(nxt)

word = random.choice(words)
out = [word]
for _ in range(12):
    if word not in chain:
        break
    word = random.choice(chain[word])
    out.append(word)
print(" ".join(out))

Sudoku Solver (backtracking) HARD

Build: fill a 9×9 grid by trying numbers and backing out of dead ends.

Minesweeper (reveal logic) HARD

Build: place mines, count neighbours, and flood-fill the empty cells.

Text Adventure Game HARD

Build: branching story rooms driven by the player's choices (functions calling functions).

Snake Game (pygame) HARD

Build: the arcade classic with pygame. Needs pip install pygame and a desktop window — it won't run in the browser.

Photo Manipulation (Pillow) HARD

Build: open an image and edit pixels — grayscale and a colour invert. Needs pip install pillow.

Maze Solver (BFS pathfinding) HARD

Build: find the shortest path through a maze with breadth-first search.

Pong (pygame) HARD

Build: paddle vs. wall pong with a bouncing ball. Needs pygame + a window — won't run in the browser.

Space Shooter (pygame) HARD

Build: move, shoot, and destroy falling enemies for points. Needs pygame + a window.

Platformer (pygame) HARD

Build: a jumping square with gravity and a ground to land on. Needs pygame + a window.

2048 (console) HARD

Build: the addictive sliding-tile game: slide with WASD, merge equal tiles, reach 2048.

Connect Four (vs AI) HARD

Build: drop pieces into a 7-wide board; the AI takes winning moves and blocks yours.

Battleship (vs computer) HARD

Build: the computer hides 3 ships on a 5×5 grid — call your shots and sink the fleet.

Conway's Game of Life HARD

Build: cells live and die by four simple rules — watch a glider walk across your terminal.

Huffman Compression HARD

Build: the algorithm inside ZIP: build the tree, encode the text, prove the round-trip, measure the savings.

Mini JSON Database HARD

Build: build your own tiny MongoDB: insert, query by field, delete — persisted to a JSON file.

Mini Template Engine HARD

Build: how Flask/Django templates work inside: {{ variables }} and {% for %} loops via regex.

Neural Network From Scratch HARD

Build: no libraries — just math: a tiny network learns XOR by backpropagation.

Genetic Algorithm HARD

Build: evolution in 40 lines: random strings breed, mutate and converge on a target phrase.

A* Pathfinding HARD

Build: the algorithm behind game NPCs and GPS routing — watch it thread a maze optimally.

Mini Language Interpreter HARD

Build: write your own programming language: a tokenizer, a recursive-descent parser and variables.

Sudoku Generator HARD

Build: not just solving — generating: build a full valid board, then carve out clues while keeping the solution unique.

Boggle Solver HARD

Build: find every dictionary word hidden in a 4×4 letter grid — DFS with prefix pruning.

Virtual File System HARD

Build: build a working shell — mkdir, cd, ls, touch, write, cat, pwd — over an in-memory tree.

File Encryption Tool HARD

Build: encrypt any file with an XOR keystream + base64, decrypt it back, and prove the bytes match.

Stock Portfolio Tracker (FIFO) HARD

Build: track buys and sells the way accountants do: FIFO lots, realized gains, average cost.

Text Editor (tkinter GUI) HARD

Build: a real windowed editor with New/Open/Save, a menu bar and a live word count.

HTTP Server From Scratch HARD

Build: no frameworks, no http.server — raw sockets: parse the request line, speak the protocol, serve a page.

🎉 That's the entire Python course on one page — from print() to OOP, modules, automation and machine learning. You're ready to build real things! Bookmark this page and come back whenever you need a quick reminder.