2014-04-19 53 views
2

這裏是我的功能的簡化版本,比較三組數字,發現兩組具有最高相關:爲什麼我的Python for循環remove()改變在循環之前聲明的變量?

inputs = ['vars_one', 'vars_two', 'vars_three'] 
def MostCorrelatedInputs(inputs): 
    correlation = 0 
    saved_inputs = inputs 
    for i in inputs: 
     testlist = saved_inputs 
     testlist.remove(i) 
     new_correlation = FindCorrelation(testlist) 
     if new_correlation > correlation: 
      correlation = new_correlation 
      outputs = testlist 
    return outputs 

的問題是,當我運行的功能,似乎remove()功能改變saved_inputs變量,即使我在inputs上調用它。這是垃圾收集的問題嗎?爲什麼save_inputs變量被我的for循環修改,如果remove()有望改變這個變量,是否有更好的方法來實現我的目標?

回答

3

我會給你一個提示:

>>>a = [1,2,3] 
>>>b = a 
>>>b.remove(1) 
>>>a 
[2, 3] 

這是因爲b引用相同的對象a呢!如果您從b中刪除某些東西,則您將從a也引用的對象中刪除它。要改變這一點,就像在創建一個副本一樣,

>>>b = a[:] 
>>>b.remove(1) 
>>>a 
[1, 2, 3] 
>>>b 
[2, 3] 
+0

哇 - 顯然是學習Python如何工作,謝謝! – YPCrumble

+1

@YPCrumble不客氣,這是一個非常常見的錯誤。這裏看起來像一個很好的閱讀:http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/ – Dunno

0

你聲明測試列表引用與輸入相同的引用。

所以,如果你想testlist只包含的值,而不是引用,你需要做的名單如下:

inputlist = inputs[:] 
1

所以,當你做一個:

saved_inputs = inputs 

testlist = saved_inputs 

testlist和saved_inputs都引用相同的對象/列表 - 輸入。

您需要獲得類似於列表的「深層複製」的內容。即

要引用您的示例代碼:

testlist = saved_inputs 

testlist.remove('vars_one') 

print testlist 
print saved_inputs 

這將導致:

['vars_two', 'vars_three'] 
['vars_two', 'vars_three'] 

你必須做這樣的事情:

testlist = list(saved_inputs) 

testlist.remove('vars_one') 

print testlist 
print saved_inputs 

要得到的結果:

['vars_two', 'vars_three'] 
['vars_one', 'vars_two', 'vars_three'] 

我認爲這是你的期望。