0

I've written the following code that should take two sets of xyz points and move them closer to each other, for example, the point x1 in list 1 should move to the point x1 in list 2 etc. This should happen over a number of steps, so if I want it to happen over 5 steps, I'll be given five lists, list1, list2, and three intermediate lists.

    def generate_steps(p1, p2, steps):  # p1 = list1, p2 = list2
        percent = 1.0 / float(steps - 1)
        points = []  # list of the lists
        for i in range(steps):
            nudged = nudge(p1, p2, (i * percent))  # generates a point in between l1 and l2
            print 'appending %s to the list points' % p1[0]
            points.append(p1)  # appends list p1 to the list points
        return points

    def nudge(t1, t2, percent): # t1 = list1, t2 = list2
        temp = t1  # copies t1 as a temporary variable, temp
        for i in range(len(t1)):
            delta_z = (t1[i][-1]) - (t2[i][-1])  # finds the difference between the points in each list
            delta_y = (t1[i][-2]) - (t2[i][-2])
            delta_x = (t1[i][-3]) - (t2[i][-3])
            step_x = percent * delta_x  # calculates how far the step must be taken
            step_y = percent * delta_y
            step_z = percent * delta_z
            temp[i][-1] = t1[i][-1] - step_z  # modifies temp to be closer to the list l2
            temp[i][-2] = t1[i][-2] - step_y
            temp[i][-3] = t1[i][-3] - step_x
        return temp

    pointss = generate_steps(l1, l2, 5)

    for i in range(len(pointss)):
        print i
        print pointss[i]

When I print p1 in the loop, I'll get a series of different values, even though I can't find anywhere in the code that should make p1 change:

    appending [1.0, 'T', 230.0, 'ZN', 0.00215020500632, 0.001299689016483, 0.06892444046125] to the list points
    appending [1.0, 'T', 230.0, 'ZN', 0.0018009683265599401, 0.00111555626549302, 0.06920025442698] to the list points
    appending [1.0, 'T', 230.0, 'ZN', 0.001242189638943844, 0.0008209438639090519, 0.069641556772148] to the list points
    appending [1.0, 'T', 230.0, 'ZN', 0.0007392888200893575, 0.0005557927024834807, 0.0700387288827992] to the list points
    appending [1.0, 'T', 230.0, 'ZN', 0.0004710750500336315, 0.0004143787497231761, 0.07025055400847985] to the list points

Even stranger, when I print the list points, which the values of p1 were appended each time during the loop, every point is the same, although it is not the starting point, but the end point:

    [1.0, 'T', 230.0, 'ZN', 0.0004040216075197, 0.0003790252615331, 0.0703035102899]
    [1.0, 'T', 230.0, 'ZN', 0.0004040216075197, 0.0003790252615331, 0.0703035102899]
    [1.0, 'T', 230.0, 'ZN', 0.0004040216075197, 0.0003790252615331, 0.0703035102899]
    [1.0, 'T', 230.0, 'ZN', 0.0004040216075197, 0.0003790252615331, 0.0703035102899]
    [1.0, 'T', 230.0, 'ZN', 0.0004040216075197, 0.0003790252615331, 0.0703035102899]

I know I should be appending the point 'nudged' to the list points, but this results in the same thing, and right now I'm more curious as to why the value of p2 is changing, and why it is not appending to the list properly.

  • *temp = t1 # copies t1 as a temporary variable, temp*: No, it doesn't create a copy. You created an additional reference. – Martijn Pieters Oct 03 '16 at 09:08
  • If I create a variable foo = 5, and then another variable bar = foo, then I take 2 away from bar, and print both variables, I'm left with foo = 5 and bar = 3. Why is this not the case in my code? Also, how would I go about making a copy instead of an additional reference? – M. Iwasaki Oct 03 '16 at 09:13
  • You are assigning new objects to a name, and those objects are immutable. `5 - 2` produces a *new* `int` object `2` that is then assigned to `bar`, while `foo` still points to `5`. You are not assigning a new object to `temp`; you are assigning to `temp[index1][index2]`, modifying the object `temp[index]` points to. Other names *also* point to that same object, the references are shared. See [this great presentation on names in Python](http://nedbatchelder.com/text/names.html) to understand more. I've duped you to the canonical post on how to create copies of lists. – Martijn Pieters Oct 03 '16 at 09:17
  • Thank you for this great explanation, it is very helpful!! – M. Iwasaki Oct 03 '16 at 09:21
  • I changed the code nudge from `temp = t1` to `temp = list(t1)` and that didn't help, so I created a copy of p1 in generate steps: `copy = list(p1)` and replaced `nudged = nudge(p1, p2, percent)` to `nudged = nudge(copy, p2, percent)`. However, the value of p1 is still changing. Does list() not create a copy of a list? I have also tried `temp = t1[:]` and that did not help either. – M. Iwasaki Oct 03 '16 at 09:48
  • You have a list of lists; `temp = [sublist[:] for sublist in t1]` creates copies of the contained lists first, building a new outer list to hold this. Or use `copy.deepcopy(t1)` (slower). `list()` creates a *shallow* copy of the list, so copying the contained references to a new list object. – Martijn Pieters Oct 03 '16 at 09:49

0 Answers0