7  The Mean

import matplotlib.pyplot as plt
from dsft.distributions import gaussian_sample, cauchy_sample, mean

def running_mean(sample_fn, n):
    xs = [sample_fn() for _ in range(n)]
    return [mean(xs[:i]) for i in range(1, n + 1)]

n = 5000
plt.plot(running_mean(gaussian_sample, n), label="Gaussian")
plt.plot(running_mean(cauchy_sample, n), label="Cauchy")
plt.legend()
plt.title("Running mean: one converges, one doesn't")

Python will always compute sum(xs) / len(xs). That doesn’t mean the number it returns estimates anything.

7.1 Summary

Build it, then watch it fail:

import random

def mean(xs):
    return sum(xs) / len(xs)

def running_mean(sample_fn, n):
    xs = [sample_fn() for _ in range(n)]
    return [mean(xs[:i]) for i in range(1, n + 1)]

def cauchy_sample():
    return random.gauss(0, 1) / random.gauss(0, 1)

Plotting running_mean for a Gaussian generator against a Cauchy generator across n = 1 to 50,000 makes the point without needing a proof first: one settles, the other keeps lurching, because the Cauchy mean doesn’t converge to anything — it’s undefined. The takeaway is stated plainly: Python will always compute sum(xs)/len(xs). That doesn’t mean the number it returns estimates anything.