Python为什么要修改循环外的列表



对于此列表:

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

我运行sliding_tristep()方法,其中包括predict()window()方法:

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

当我运行sliding_tristep(current_trace)时,在print current_input, accumulator行的输出中,我注意到current_input已经被修改,尽管它不在进行sliding_tristep(current_trace)计算的while循环中。

我想知道为什么会发生这种事?python怎么可能修改一个在后续循环中根本不使用的列表呢。

我运行sliding_tristep(current_trace),在print current_input, accumulator行的输出中,我注意到current_trace已被修改

刚刚测试了您的代码:

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

current_trace不会被修改

我想知道为什么会发生这种情况?python怎么可能修改一个在后续循环中根本不使用的列表呢。

不过,我猜你指的是current_input,而不是current_trace

current_input会被修改,因为trace是对current_input的引用,跟踪会被修改。

如果您想将current_input复制为trace,这里有一种方法:

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

应用于您的代码:

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

如果你不修改列表中的元素(由于整数是不可变的,你不能),你可以像我在前面的例子中建议的那样进行浅层复制。如果您使用的是可变对象(lists或其他类型的对象),那么您需要使用copy模块进行深度复制。看看这个答案:https://stackoverflow.com/a/184660/1290438关于这个主题。

使用trace.extend(current_input)而不是trace = current_input解决了问题。但是trace列表必须被预先初始化。

解决方案看起来像:

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

相关内容

  • 没有找到相关文章