更新列表中的某些元素

时间:2015-11-20 21:30:47

标签: python

我想创建一个包含初始点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;

但这似乎会在循环中来回改变元素。

2 个答案:

答案 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]]

如果这就是你所需要的,那么这个双线函数比上面的任何一个怪物都更具可读性和可理解性。

记住: