为啥我的原始列表发生了变化?
Posted
技术标签:
【中文标题】为啥我的原始列表发生了变化?【英文标题】:Why does my original list change?为什么我的原始列表发生了变化? 【发布时间】:2013-05-13 14:57:54 【问题描述】:我写了一个函数 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
【问题讨论】:
关于复制列表:***.com/a/184660/577423 值得注意的是,您不需要临时变量来在 Python 中进行交换 -solution[n], solution[m] = solution[m], solution[n]
。这更短,更易读,也更高效。
可能重复:***.com/questions/11993878/…
【参考方案1】:
SwapCities
正在改变solution
的内容。
由于solution
指向与IncumbentSolution
相同的列表,因此IncumbentSolution
中的值也发生了变化。
要保留 IncumbentSolution
中的原始值,请制作列表的新副本:
tmpsolution = list(IncumbentSolution)
制作原始列表的浅表副本。由于IncumbentSolution
的内容是不可变的数字,因此浅拷贝就足够了。如果包含的内容(例如 dicts
)也在发生变异,那么您需要制作列表的深层副本:
import copy
tmpsolution = copy.deepcopy(IncumbentSolution)
【讨论】:
我总是推荐使用list(IncumbentSolution)
。它做同样的工作,但更具可读性。 [:]
通常会让新的 Python 用户感到困惑(看看有多少关于它的问题仅在 SO 上),虽然这并不总是不使用某些东西的好理由,但当我们手头有更好的替代品时.
@Lattyware:好主意。使用arr[:]
会让人困惑,尤其是在使用NumPy
时,因为它返回的是视图,而不是副本。【参考方案2】:
那是因为你修改了函数内部的列表。
通过将列表传递给函数,您只需创建对同一对象的另一个引用,
solution
和 IncumbentSolution
实际上指向同一个列表对象。
您应该使用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)
【讨论】:
以上是关于为啥我的原始列表发生了变化?的主要内容,如果未能解决你的问题,请参考以下文章
我的 Redux 状态发生了变化,为啥 React 没有触发重新渲染?
printList函数中原始头指针没有改变,但插入节点时列表确实发生了变化