If I interpreted correctly what you wanted to do from your explanation and code:
def perturbate(x, h):
"""
Given an initial point x = [x0, x1, ..., xn]
Returns a list of points containing the original point and,
for every coordinate, "perturbations" of that point created
by adding and subtracting 'h' to the coordinate.
"""
# start with the original point plus
# 2 copies of it for every coordinate
points = [x[:] for i in range(len(x)*2 + 1)]
for coordinate_index in range(len(x)):
points[coordinate_index*2 + 1][coordinate_index] -= h
points[coordinate_index*2 + 2][coordinate_index] += h
return points
Which gives:
>>> perturbate([1.0,2.0], 1.0)
[[1.0, 2.0], [0.0, 2.0], [2.0, 2.0], [1.0, 1.0], [1.0, 3.0]]
So basically your code was almost correct (but not really clear, the generic-named variables don't help), except for the "results" inizialization: when you do [x] * 5
, where x
is a mutable object, you're creating a list of 5 times the same object. If you change a property of that object, it will change in all the indices, because they reference the same object!
>>> a = [[0,0]] * 5
>>> a
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]
>>> a[0][0] = 1
>>> a
[[1, 0], [1, 0], [1, 0], [1, 0], [1, 0]]
>>>
Also the hardcoded 5
assumes 2-dimensional points. But if we assume 2 dimensional points, than why using the len of the point instead of just using a surely simpler and clearer "hardcoded" implementation?