Overall, it was very good. The main issues were:
$\langle x^2\rangle = \frac{1}{ N_{\rm walker} }\sum\limits_{j=0}^{N_{\rm walker}} x_j^2.$
and not
$\langle x\rangle^2 = \frac{1}{ N_{\rm walker} }\left(\sum\limits_{j=0}^{N_{\rm walker}} x_j\right)^2.$
nsteps = 1000
ndim = 1
nwalkers = 100
distances = numpy.ndarray((nwalkers, nsteps+1))
distances2 = numpy.ndarray((nwalkers, nsteps+1))
for i in range(nwalkers):
w=walker(numpy.zeros(ndim),ndim=ndim)
ys=w.doSteps(nsteps)
distances[i] = ys[:,0]
dist2=numpy.array([sum(yy*yy) for yy in ys])
distances2[i] = dist2
plt.plot(range(nsteps+1), numpy.mean(distances,0),label="$<x>$")
plt.plot(range(nsteps+1), numpy.mean(distances2,0),label="$<x^2>$")
plt.legend()
plt.title("average position and squared position")
plt.xlabel("number of steps")
plt.ylabel("average over 100 walkers")
nsteps=100
for ndim in range(1,5):
nwalkers=400
distances=numpy.ndarray((nwalkers,nsteps+1),dtype=float)
for i in range(nwalkers):
w=walker(numpy.zeros(ndim),ndim=ndim)
ys=w.doSteps(nsteps)
dist2=numpy.array([sum(yy*yy) for yy in ys])
distances[i]=dist2
plt.plot(range(nsteps+1),numpy.mean(distances,0),label="ndim={0}".format(ndim))
plt.legend()
ndim=2
nwalkers=500
rand_pos = numpy.random.uniform(size=(nwalkers,2))
plt.figure(figsize=(18,6))
for i, nsteps in enumerate([10,100,500]):
plt.subplot(131+i)
plt.xlim((-3,4))
plt.ylim((-3,4))
finalPosx = []
finalPosy = []
for i in range(nwalkers):
w=walker(rand_pos[i],ndim=ndim, step_size=0.05)
numpy.random.seed(i)
ys=w.doSteps(nsteps)
yst=ys.T
x, y = ys[-1]
finalPosx.append(x)
finalPosy.append(y)
plt.title("after {} steps".format(nsteps))
plt.xlabel("$x$")
plt.ylabel("$y$")
plt.title("after {} steps".format(nsteps))
plt.scatter(finalPosx, finalPosy, alpha=0.1)