Python v2 logo — two snakes, red and blue python™v2
▶ Subscribe

The Python v2 Tutorial

Ten short lessons from zero to writing real programs. Every example on this page is runnable — press Load & run and watch the interpreter do its thing, right here in your browser. Already know Python? You'll finish this in ten minutes.

▶ The Sandbox

This is the real Python v2 interpreter running in your browser. Edit anything and press Run (or Ctrl+Enter). Every “Load & run” button below drops its example here.

Need a full workspace? The new Playground adds line numbers, Python v2 and Classic compatibility modes, command history, a separate error terminal, downloadable source, and a live website workshop. Start here for each lesson, then move there when you want to experiment.

01 Hello, World!

Python v2 programs are plain text files ending in .pyv2. The print function shows things on screen, and # starts a comment.

# hello.pyv2
print("Hello, World!")
print("2 + 2 =", 2 + 2)

On your computer, run it with python3 -m pyv2 hello.pyv2 — get the language here.

02 Variables & Values

Just write name = value — no declarations, no semicolons. Python v2 has numbers, strings, booleans, and nil (the “nothing” value). Ask type(x) whenever you're curious.

name = "Ada"
age = 36
pi = 3.14
coding = true
gift = nil

print(name, age, pi, coding, gift)
print(type(name), type(age), type(coding), type(gift))

03 Math

All the usual operators, plus three you'll love: // is floor division, % is remainder, and ** is power. Division always gives you a real number — 10 / 4 is 2.5, not 2.

print(10 / 4, 10 // 4, 7 % 3, 2 ** 10)
print(-7 // 2, -7 % 3)        # floored, Python-style
print("n=" + 42)              # strings + numbers just work

04 Strings & F-Strings

The star of the show: f-strings. Put f before a string and {anything} inside it — expressions included. Strings come with friendly methods: upper, split, contains, …

name = "python v2"
print(f"Hello, {name}!")
print(f"next year: {2026 + 1}, fast: {2 ** 8}")
print(f"{{braces}} survive when doubled")

print(name.upper(), name.title())
print("a,b,c".split(",").join(" - "))
print("hello".contains("ell"), "hello".slice(1, 3))

05 Lists

Lists keep things in order. Index with xs[0] (or xs[-1] for the last), and use the methods that spark joy: push, sort, join, …

xs = [3, 1, 2]
xs.push(4)
print(xs, xs.sort(), xs[-1])

names = ["Ada", "Grace"]
names.insert(0, "Edsger")
print(names, names.join(", "), len(names))
print([1, 2] + [3], [1, 2] * 2)
print("sum:", sum(xs), "numbered:", enumerate(names, 1))
print("paired:", zip(names, [36, 85, 92]))

06 Maps

Maps hold labeled values. Bare keys become strings, dot access reads them, and get(key, default) never explodes when the key is missing.

hero = {
    name: "Ada",
    scores: [10, 20, 30],
}
hero.city = "London"

print(hero.name, hero["city"])
print(hero.scores)
hero.scores.push(40)
print(hero.scores)
print(hero.get("pet", "none"), hero.has("name"))

07 Decisions

if / elif / else blocks end with end — no indentation errors, ever. And the ternary reads like a question: ok ? "yes" : "no".

score = 87

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
else:
    grade = "C"
end

print(f"score {score} → grade {grade}")
print(score > 60 ? "passed" : "failed")

08 Loops

for x in … walks lists, strings, maps and range(). while repeats until you say stop — with break and continue when you need them.

for i in range(1, 6):
    print(f"i is {i}")
end

total = 0
for n in [1, 2, 3, 4, 5, 6]:
    if n % 2 == 0:
        continue        # skip evens
    end
    total += n
end
print("sum of odds:", total)

for ch in "abc":
    print(ch)
end

09 Functions & Closures

Define functions with fn, give values back with return. Functions are just values — pass them around. And inner functions remember the world they were born in (real closures, no nonlocal nonsense).

fn greet(name):
    return f"Hello, {name}!"
end

fn make_counter():
    n = 0
    fn bump():
        n += 1
        return n
    end
    return bump
end

print(greet("World"))

counter = make_counter()
counter()
counter()
print("count:", counter())

sq = fn(x): return x * x end
print("7² =", sq(7))

10 Errors, Recovery & Cleanup

Failures carry a kind, message, source line, and call trace. Protect work with try, recover in catch error, and put cleanup in finally so it runs even during a return or loop jump. Use raise for your own application errors.

fn divide(a, b):
    assert(b != 0, "b must not be zero")
    return a / b
end

try:
    print(divide(10, 0))
catch error:
    print(error.kind + ":", error.message)
    print("line:", error.line)
finally:
    print("calculation finished")
end

try: raise {kind: "ConfigError", message: "port required"}
catch error: print(error.kind, error.message)
end

★ What's Next

You now know the whole language. Seriously — that was it. Go build something:

Graduation project: write FizzBuzz from memory, the Python v2 way —

for i in range(1, 16):
    if i % 15 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)
    end
end