Kristof Pal
Kristof Pal

Reputation: 1026

Why does Python modify the list which is out of the loop?

for this list:

current_trace = [[3,5,1,5,7,9,4]]

I run the sliding_tristep() method, which includes the predict() and window() methods:

def predict(lst):
    print "predicting for", lst
    print "result", max(lst) + 0.0
    return max(lst) + 0.0

def window(lst, n=3):
    for x in range(1, len(lst)+1): # or len(l)+n to continue till the end
        yield(lst[max(0, x-n):x])

def sliding_tristep(full_trace, future_step = 2, window_size = 3):

    for user_trace in full_trace:
        for current_input in window(user_trace):
            counter = 0
            trace = current_input
            accumulator = []
            while counter <= future_step:
                next_prediction = predict(trace)  
                trace.append(next_prediction)
                accumulator.append(next_prediction)
                trace = trace[-window_size:]
                counter += 1

            print current_input, accumulator

When I run sliding_tristep(current_trace), in the output for the print current_input, accumulator line I notice that the current_input has been modified although it is out of the while loop which makes the calculations in sliding_tristep(current_trace).

I wonder why does this happen? How is that possible for python to modify a list which is not used at all in the subsequent loop.

Upvotes: 2

Views: 86

Answers (2)

zmo
zmo

Reputation: 24812

I run sliding_tristep(current_trace), in the output for the print current_input, accumulator line I notice that the current_trace has been modified

just tested your code:

>>> current_trace = [[3,5,1,5,7,9,4]]
>>> sliding_tristep(current_trace)
...
>>> current_trace
[[3, 5, 1, 5, 7, 9, 4]]

current_trace does not get modified.

I wonder why does this happen? How is that possible for python to modify a list which is not used at all in the subsequent loop.

Though, I guess you meant current_input and not current_trace.

current_input gets modified, because trace is a reference to current_input and trace gets modified.

If you want to make a copy of current_input as trace, here's one way to do it:

>>> foo = [1,2,3]
>>> bar = foo[:]
>>> bar.append(4)
>>> foo
[1, 2, 3]
>>> bar
[1, 2, 3, 4]

applied to your code:

def sliding_tristep(full_trace, future_step = 2, window_size = 3):
    for user_trace in full_trace:
        for current_input in window(user_trace):
            counter = 0
            trace = current_input[:] # make a copy of current_input
            accumulator = []
            while counter <= future_step:
                next_prediction = predict(trace)  
                trace.append(next_prediction)
                accumulator.append(next_prediction)
                trace = trace[-window_size:]
                counter += 1                    
            print current_input, accumulator

If you don't modify the elements of the list (and as integers are non-mutable, you can't), you can do the shallow copy as I'm suggesting you in the aforementioned example. If you're using mutable objects (lists or other kind of objects), then you want to do a deep copy using the copy module. Look at this answer: https://stackoverflow.com/a/184660/1290438 on this topic.

Upvotes: 2

Kristof Pal
Kristof Pal

Reputation: 1026

using trace.extend(current_input) , instead of trace = current_input solves the problem. although, a trace list has to be initialized beforehand.

The solution would look like:

def sliding_tristep(full_trace, future_step = 2, window_size = 3):

    for user_trace in full_trace:
        for current_input in window(user_trace): 
            counter = 0
            trace = [] #here is the solution
            trace.extend(current_input) #here is the solution
            accumulator = []
            while counter <= future_step:
                next_prediction = predict(trace)  
                trace.append(next_prediction)
                accumulator.append(next_prediction)
                trace = trace[-window_size:]
                counter += 1

Upvotes: 0

Related Questions