Python 原始列表的元素在深度副本发生更改时发生更改
我有一个全局列表(列表)变量。我将全局列表的浅表副本作为参数发送给另一个函数 令人惊讶的是,当我从调用的函数中的参数中删除一些元素时,原始列表会发生变化 有人能告诉我为什么会发生这种情况,以及如何防止这种情况发生吗 以下是简化的代码示例:Python 原始列表的元素在深度副本发生更改时发生更改,python,python-2.7,Python,Python 2.7,我有一个全局列表(列表)变量。我将全局列表的浅表副本作为参数发送给另一个函数 令人惊讶的是,当我从调用的函数中的参数中删除一些元素时,原始列表会发生变化 有人能告诉我为什么会发生这种情况,以及如何防止这种情况发生吗 以下是简化的代码示例: def saveCandidateRoutes(candidateRoutes): for route in candidateRoutes: if route: # check if the list,
def saveCandidateRoutes(candidateRoutes):
for route in candidateRoutes:
if route: # check if the list, 'route', is empty.
tweetId = route.pop(0)
stanox = route.pop(-1)
....
def main():
global allCandidatePaths
copyOfAllCandidatePaths= list(allCandidatePaths) # making a deep copy
result = saveCandidateRoutes(copyOfAllCandidatePaths)
我想你对这些条款感到困惑 浅复制是一种复制类型,其中复制列表的元素仍然绑定到与原始列表元素相同的内存值 你要找的是deepcopy 而且:
我想你对这些术语感到困惑 浅复制是一种复制类型,其中复制列表的元素仍然绑定到与原始列表元素相同的内存值 你要找的是deepcopy 而且:
浅层副本复制对象,但不复制其任何属性。对于列表,这意味着它的元素被分配给新列表的元素。如果元素是int,则会得到一个全新的列表,因为int是一个基元类型*,因此不需要复制它。如果元素是列表,就像在二维列表中一样,它们将被指定给副本,因此每个元素有两个引用,每个列表中有一个引用。如果要复制内部列表的元素,则需要一个深度副本,它递归地复制每个对象的属性(在本例中为元素)
*实际上,基本类型和非基本类型之间没有区别,但这与本解释范围内的工作方式相同。浅拷贝复制对象,但不复制其任何属性。对于列表,这意味着它的元素被分配给新列表的元素。如果元素是int,则会得到一个全新的列表,因为int是一个基元类型*,因此不需要复制它。如果元素是列表,就像在二维列表中一样,它们将被指定给副本,因此每个元素有两个引用,每个列表中有一个引用。如果要复制内部列表的元素,则需要一个深度副本,它递归地复制每个对象的属性(在本例中为元素)
*实际上,基本类型和非基本类型之间没有区别,但这与本解释范围内的工作方式相同。python使用对对象的引用,这意味着
AllCandidatePath
和candidateRoutes
都指向内存中的相同列表,您可以使用这两个选项来更改列表
为了防止这种情况发生,请在函数的开头添加此指令candidateRoutes=list(candidateRoutes)
。list()
函数将在内存中创建原始列表的另一个副本,并将其引用分配给candidateRoutes
因此,当您使用
candidateRoutes
时,您将不会处理主函数中的原始列表,而是处理另一个列表。python使用对对象的引用,这意味着allCandidatePaths
和candidateRoutes
都指向内存中的相同列表,您可以使用这两个选项来更改列表
为了防止这种情况发生,请在函数的开头添加此指令candidateRoutes=list(candidateRoutes)
。list()
函数将在内存中创建原始列表的另一个副本,并将其引用分配给candidateRoutes
因此,当您使用
candidateRoutes
时,您将不会处理主功能中的原始列表,而是处理另一个列表。我认为您需要一个关于浅拷贝和深拷贝的快速提醒,以及如何制作深拷贝
>>> a = [[1,2], [3,4]] # a list of mutable elements
>>> b = a[:]
>>> c = list(a)
b
和c
都是a
的浅拷贝,您可以检查a
、b
和c
是否是不同的对象,因为它们不共享相同的id
>>> id(a)
140714873892592
>>> id(b)
140714810215672
>>> id(c)
140714873954744
然而,a
、b
和c
的每个元素仍然是我们在定义a时创建的列表[1,2]
和[3,4]
的参考。当我们对列表中的一个项目进行变异时,这一点变得很清楚:
>>> c[1][1] = 42
>>> a
[[1, 2], [3, 42]]
>>> b
[[1, 2], [3, 42]]
>>> c
[[1, 2], [3, 42]]
如您所见,第二个列表的第二个元素在a
、b
和c
中发生了更改。
现在,要制作a
的深度副本,您有几个选项。一种是列表理解,您可以在其中复制每个子列表:
>>> d = [sublist[:] for sublist in a]
>>> d
[[1, 2], [3, 42]]
>>> d[1][1] = 23
>>> d
[[1, 2], [3, 23]]
>>> a
[[1, 2], [3, 42]]
如您所见,a
中的42没有变为23
,因为a
和d
中的第二个列表是不同的对象:
>>> id(a[1])
140714873800968
>>> id(d[1])
140714810230904
另一种创建深度副本的方法是使用copy.deepcopy
:
>>> from copy import deepcopy
>>> e = deepcopy(a)
>>> e
[[1, 2], [3, 42]]
>>> e[1][1] = 777
>>> e
[[1, 2], [3, 777]]
>>> a
[[1, 2], [3, 42]]
我想你需要一个关于浅拷贝和深拷贝的快速提醒,以及如何制作深拷贝
>>> a = [[1,2], [3,4]] # a list of mutable elements
>>> b = a[:]
>>> c = list(a)
b
和c
都是a
的浅拷贝,您可以检查a
、b
和c
是否是不同的对象,因为它们不共享相同的id
>>> id(a)
140714873892592
>>> id(b)
140714810215672
>>> id(c)
140714873954744
然而,a
、b
和c
的每个元素仍然是我们在定义a时创建的列表[1,2]
和[3,4]
的参考。当我们对列表中的一个项目进行变异时,这一点变得很清楚:
>>> c[1][1] = 42
>>> a
[[1, 2], [3, 42]]
>>> b
[[1, 2], [3, 42]]
>>> c
[[1, 2], [3, 42]]
如您所见,第二个列表的第二个元素在a
、b
和c
中发生了更改。
现在,要制作a
的深度副本,您有几个选项。一种是列表理解,您可以在其中复制每个子列表:
>>> d = [sublist[:] for sublist in a]
>>> d
[[1, 2], [3, 42]]
>>> d[1][1] = 23
>>> d
[[1, 2], [3, 23]]
>>> a
[[1, 2], [3, 42]]
如您所见,a
中的42没有改变t