2013-05-18 29 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) 
相关问题