我想创建一个包含初始点x = [x0 x1]
和扰动点y1 = [x0+h x1]
,y2 = [x0-h x1]
,y3 = [x0 x1+h]
等的列表。我试过这个:
xs = [x]*5;
for i in range(len(x)):
if isinstance(h, float):
xs[2*i+1][i] -= h;
xs[2*i+2][i] += h;
但这似乎会在循环中来回改变元素。
答案 0 :(得分:2)
如果我从您的解释和代码中正确解释了您想要做的事情:
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
给出了:
>>> 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]]
所以基本上你的代码几乎是正确的(但不是很清楚,通用命名的变量没有帮助),除了“结果”inizialization:当你做[x] * 5
时,x
是一个可变对象,你创建的列表是同一个对象的5倍。如果更改该对象的属性,它将在所有索引中更改,因为它们引用相同的对象!
>>> 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]]
>>>
硬编码5
也假定为二维点。但是,如果我们假设2维点,那么为什么使用点的len而不是仅仅使用更简单和更清晰的“硬编码”实现呢?
答案 1 :(得分:2)
我认为接受的答案是不必要的复杂,这使得难以推理,因此更难以调试和维护。它也更复杂,因为它不必要地预填充一个列表,然后它必须迭代。
如上所述的一般性解决方案如下:
def perturbate(x, h):
perturbations = [x] # initialize with original point first
for i, _ in enumerate(x): # no range(len())
shifted_down = x[:]
shifted_down[i] -= h
perturbations.append(shifted_down)
shifted_up = x[:]
shifted_up[i] += h
perturbations.append(shifted_up)
return perturbations
除此之外,如果您在2D中工作,这种支持多达n维点的通用解决方案远不如仅仅拼写出来那么可读:
def perturbate(point, h):
x, y = point
return [[x, y], [x-h, y], [x+h, y], [x, y-h], [x, y+h]]
如果这就是你所需要的,那么这个双线函数比上面的任何一个怪物都更具可读性和可理解性。
记住: