2013-05-18 28 views
0

我寫了一個函數SwapCities,它能夠交換列表中的條目3和4。爲什麼我的原始列表更改?

所以f.e. [0,1,2,3,4]應該變成[0,1,2,4,3]。這個功能完美的工作,但奇怪的是我的原始列表也改變了我不想要的。

這是我的代碼:

def SwapCities(solution): 
    n = 3##randint(0,NumberOfCities-1) 
    m = 4##randint(0,NumberOfCities-1) 
    result = solution 
    temp1 = solution[n] 
    temp2 = solution[m] 
    result[n] = temp2 
    result[m] = temp1 
    return result 

print "Start" 
IncumbentSolution = list(x for x in range(0,NumberOfCities)) 
print IncumbentSolution 

print "After swap" NewSolution = SwapCities(IncumbentSolution) 
print NewSolution 

print "Original solution" 
print IncumbentSolution 

我得到以下結果:

How many cities? 
8 Start [0, 1, 2, 3, 4, 5, 6, 7] 
After swap [0, 1, 2, 4, 3, 5, 6, 7] 
Original solution [0, 1, 2, 4, 3, 5, 6, 7] (why did this change?!) 

正如你可以看到我原來的解決方案改變了它不應該這樣做。

我不知道爲什麼會發生這種情況。即使當我更改代碼以使更改應用於原始列表的副本時,我也會得到此結果。有人能解釋我做錯了什麼嗎?

IncumbentSolution = list(x for x in range(0,NumberOfCities)) 
print "Start" 
print IncumbentSolution 

print "After swap" 
tmpsolution = IncumbentSolution 
NewSolution = SwapCities(tmpsolution) 
print NewSolution 

print "Original solution" 
print IncumbentSolution 
+0

關於複製列表:http://stackoverflow.com/a/184660/577423 – Howard

+3

值得注意你不需要臨時變量做Python中的交換 - '解決方案[N],解決方案[M ] =解[m],解[n]'。這更短,更可讀,也更高效。 –

+0

可能的重複:http://stackoverflow.com/questions/11993878/python-why-does-my-list-change-when-im-not-actually-changing-it?rq=1 – carlosdc

回答

6

SwapCities突變的solution內容。 由於solution指向與IncumbentSolution相同的列表,因此IncumbentSolution中的值也發生了變化。


要保留原始值IncumbentSolution,使列表的新副本:

tmpsolution = list(IncumbentSolution) 

使得原始列表的淺表副本。由於IncumbentSolution的內容是不可變的數字,因此淺拷貝就足夠了。如果內容包括,說,dicts這也正在發生突變,那麼你就需要做出的排行榜的深層副本:

import copy 
tmpsolution = copy.deepcopy(IncumbentSolution) 
+1

我總是推薦使用'名單(IncumbentSolution)'。它做同樣的工作,但更具可讀性。對於新的Python用戶來說,[[:]'通常會讓人感到困惑(看看有多少關於它的問題),雖然這並不總是一個不使用某些東西的好理由,但是當我們有更好的替代在眼前。 –

+0

@Lattyware:好主意。使用'arr [:]'特別是在使用'NumPy'時會令人困惑,因爲它返回一個視圖,而不是副本。 – unutbu

1

那是因爲你修改裏面的功能列表。

通過將列表傳遞給函數,您只需創建另一個對同一對象的引用,即 solutionIncumbentSolution實際上指向相同的列表對象。

您應該使用IncumbentSolution[:]將淺拷貝傳遞給函數。

>>> def func(x): 
...  return id(x) 
... 
>>> lis = range(5) 
>>> id(lis),func(lis)  #both `x` and `lis` point to the same object 
(163001004, 163001004) 

>>> id(lis),func(lis[:]) #pass a shallow copy, `lis[:]` or `list(lis)` 
(163001004, 161089068) 
相關問題