Practice playground

Write and run real Python, right here in your browser. Nothing to install, nothing to sign up for — press Run on any snippet, or Edit to make it yours first. The first run downloads Python itself (about 20 MB, once); the first plot adds matplotlib (about 8 MB more, also once).

12 starter snippets runs entirely on your device — nothing you type leaves it

Scratchpad

A blank-ish page. Press Edit, type any Python, press Run.

scratchpad.py
# Your scratchpad. Edit this code, then press Run.
name = "world"
print(f"Hello, {name}!")

total = sum(n * n for n in range(1, 11))
print("1² + 2² + … + 10² =", total)

NumPy basics

Arrays, vectorised maths and broadcasting — the floor everything else stands on.

numpy_basics.py
import numpy as np

a = np.array([1.0, 2.0, 3.0, 4.0])
print("a          =", a)
print("a * 10     =", a * 10)          # vectorised: no loop
print("a.mean()   =", a.mean())
print("a.std()    =", round(a.std(), 4))

m = np.arange(12).reshape(3, 4)
print("\nm =\n", m)
print("\ncolumn means =", m.mean(axis=0))
print("row sums     =", m.sum(axis=1))

# Broadcasting: a row vector added to every row of the matrix.
print("\nm + [100, 200, 300, 400] =\n", m + np.array([100, 200, 300, 400]))

Plot a line chart

matplotlib in the browser: the figure appears under the output.

line_plot.py
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 4 * np.pi, 200)

plt.figure(figsize=(7, 4))
plt.plot(x, np.sin(x), label="sin(x)")
plt.plot(x, np.cos(x), label="cos(x)", linestyle="--")
plt.title("Two waves")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

print("Every open figure is shown when the run finishes.")

Histogram of random data

Draw 10,000 samples from a normal distribution and look at their shape.

histogram.py
import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(seed=42)
samples = rng.normal(loc=170, scale=8, size=10_000)   # e.g. heights in cm

plt.figure(figsize=(7, 4))
plt.hist(samples, bins=40, edgecolor="white")
plt.title("10,000 draws from N(170, 8)")
plt.xlabel("value")
plt.ylabel("count")
plt.show()

print(f"mean = {samples.mean():.2f}, std = {samples.std():.2f}")

pandas: group and summarise

A tiny DataFrame, then the split-apply-combine move you will use forever.

pandas_groupby.py
import pandas as pd

df = pd.DataFrame({
    "city":  ["Hyderabad", "Mumbai", "Hyderabad", "Delhi", "Mumbai", "Delhi"],
    "month": ["Jan", "Jan", "Feb", "Jan", "Feb", "Feb"],
    "sales": [120, 200, 150, 90, 210, 130],
})
print(df, "\n")

by_city = df.groupby("city")["sales"].agg(["sum", "mean", "count"])
print(by_city, "\n")

print("Best city:", by_city["sum"].idxmax())

Linear regression by gradient descent

Fit y = wx + b from scratch and watch the loss fall — then plot the fit.

gradient_descent.py
import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(seed=0)
x = rng.uniform(0, 10, size=60)
y = 3.0 * x + 7.0 + rng.normal(0, 2.5, size=60)   # the "truth" is w=3, b=7

w, b, lr = 0.0, 0.0, 0.01
for step in range(2001):
    y_hat = w * x + b
    error = y_hat - y
    loss  = (error ** 2).mean()
    w -= lr * 2 * (error * x).mean()   # dL/dw
    b -= lr * 2 * error.mean()         # dL/db
    if step % 400 == 0:
        print(f"step {step:4d}  loss {loss:8.3f}  w {w:5.2f}  b {b:5.2f}")

plt.figure(figsize=(7, 4))
plt.scatter(x, y, s=18, alpha=0.7, label="data")
xs = np.linspace(0, 10, 2)
plt.plot(xs, w * xs + b, color="crimson", label=f"fit: y = {w:.2f}x + {b:.2f}")
plt.legend()
plt.title("Gradient descent finds the line")
plt.show()

k-means clustering

Make three blobs of points, let k-means find them, plot the result.

kmeans.py
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

rng = np.random.default_rng(seed=7)
centres = np.array([[0, 0], [6, 4], [1, 7]])
points = np.vstack([
    rng.normal(c, 0.9, size=(80, 2)) for c in centres
])

km = KMeans(n_clusters=3, n_init=10, random_state=7).fit(points)

plt.figure(figsize=(6, 5))
plt.scatter(points[:, 0], points[:, 1], c=km.labels_, s=16, cmap="viridis")
plt.scatter(km.cluster_centers_[:, 0], km.cluster_centers_[:, 1],
            marker="X", s=200, color="crimson", label="found centres")
plt.legend()
plt.title("k-means, k = 3")
plt.show()

print("Cluster sizes:", np.bincount(km.labels_))

A tiny neural net, forward pass

Two layers, ReLU, softmax — the whole forward pass in plain NumPy.

forward_pass.py
import numpy as np

rng = np.random.default_rng(seed=1)

# One input with 4 features, e.g. petal/sepal measurements.
x = np.array([5.1, 3.5, 1.4, 0.2])

# Layer 1: 4 features -> 5 hidden units, then ReLU.
W1 = rng.normal(0, 0.5, size=(5, 4))
b1 = np.zeros(5)
h = np.maximum(0, W1 @ x + b1)          # ReLU(W1·x + b1)
print("hidden activations:", np.round(h, 3))

# Layer 2: 5 hidden -> 3 classes, then softmax.
W2 = rng.normal(0, 0.5, size=(3, 5))
b2 = np.zeros(3)
logits = W2 @ h + b2

exp = np.exp(logits - logits.max())     # subtract max: numerically safe
probs = exp / exp.sum()

for i, p in enumerate(probs):
    print(f"class {i}: {p:.1%}")
print("prediction: class", int(probs.argmax()))

Train and score a classifier

The full loop on the iris flowers: split, fit, predict, score.

classifier.py
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=0, stratify=y)

model = LogisticRegression(max_iter=500).fit(X_train, y_train)

print("train accuracy:", round(model.score(X_train, y_train), 3))
print("test accuracy: ", round(model.score(X_test, y_test), 3))

sample = [[5.9, 3.0, 5.1, 1.8]]
names = load_iris().target_names
print("prediction for", sample[0], "->", names[model.predict(sample)[0]])

PCA: 64 dimensions to 2

Squash the 8×8 handwritten digits into a plane you can actually look at.

pca.py
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA

digits = load_digits()                  # 1,797 images, 64 pixels each
coords = PCA(n_components=2).fit_transform(digits.data)

plt.figure(figsize=(7, 5))
sc = plt.scatter(coords[:, 0], coords[:, 1], c=digits.target,
                 cmap="tab10", s=10, alpha=0.8)
plt.colorbar(sc, label="digit")
plt.title("Handwritten digits, projected from 64D to 2D")
plt.show()

print("Same-looking digits land near each other — with no labels used.")

Word frequencies, stdlib only

No imports beyond the standard library — Counter does the heavy lifting.

word_count.py
from collections import Counter
import re

text = """
Machine learning is the study of programs that improve with experience.
The more experience the program gets, the better the program becomes.
"""

words = re.findall(r"[a-z']+", text.lower())
counts = Counter(words)

print(f"{len(words)} words, {len(counts)} unique\n")
for word, n in counts.most_common(5):
    print(f"{word:12s} {'█' * n} {n}")

Estimate π with random darts

Throw 50,000 random points at a square and count what lands in the circle.

monte_carlo_pi.py
import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(seed=3)
n = 50_000
pts = rng.uniform(-1, 1, size=(n, 2))
inside = (pts ** 2).sum(axis=1) <= 1.0

estimate = 4 * inside.mean()
print(f"darts: {n:,}")
print(f"π est: {estimate:.5f}   (true: {np.pi:.5f})")

show = pts[:3000]                        # plot a sample, not all 50k
plt.figure(figsize=(5, 5))
plt.scatter(show[:, 0], show[:, 1], c=inside[:3000], s=4, cmap="coolwarm")
plt.gca().set_aspect("equal")
plt.title(f"π ≈ 4 × (inside / total) = {estimate:.4f}")
plt.show()