函数正在更改两个列表,而不是一个基于 Python 中基于"0"的列表



我有点困惑,为什么在恢复后两个输出都会发生变化,而它肯定应该只有一个(输出在注释中说明)。当然只有第一个应该改变吗?如果有人能给我一个关于为什么会发生这种情况的建议,我会很感激

def switcher(y):
# shifts two characters
temp = y[0]
y[0] = y[1]
y[1] = temp

sub = [[1,2,3],[1,2,3]]
switcher(sub[0])
sub
#[[2, 1, 3], [1, 2, 3]]
#restore
sub[0] = sub[1]
sub
# [[1, 2, 3], [1, 2, 3]]
switcher(sub[0])
sub
#[[2, 1, 3], [2, 1, 3]]

使用sub[0] = sub[1],您将两个列表定义为同一对象,这就是为什么后续更改将应用于这两个列表。例如,执行sub[0] = sub[1][:]以创建副本(对于列表,有更多的方法可以这样做)。

在执行sub[0] = sub[1]时,将对索引1处的值的引用(即,在您的情况下为[1, 2, 3])分配给索引0,因此最终两个列表都位于同一内存位置,其中一个的更改会对另一个进行相应的更改。

您可以使用id内建函数来验证这一点,该函数表示给定值的内存引用:

初始化后的ids:

>>> sub = [[1,2,3],[1,2,3]]
>>> [id(s) for s in sub]
[1385461417096, 1385461338824]

调用交换机后的ids:

>>> switcher(sub[0])
>>> [id(s) for s in sub]
[1385461417096, 1385461338824]

分配sub[0] = sub[1]:后的id

>>> sub[0] = sub[1]
>>> [id(s) for s in sub]
[1385461338824, 1385461338824]

正如你所看到的,在分配sub[0] = sub[1]之后,id是相同的,当修改其中一个子列表时,两个子列表都会发生变化

有问题的行是分配

sub[0] = sub[1]

分配从不复制数据。

您告诉Python,引用sub[0]sub[1]现在都指向内存中的同一列表对象(内容为[1,2,3])。

在您的特定情况下,通过在作业右侧复制一份(浅)列表,可以很容易地解决此问题。

sub[0] = sub[1][:]

引用有问题。通过定义:

sub = [[1,2,3],[1,2,3]]

你创建了一个由两个不同列表组成的列表,但当你这样做时:

sub[0] = sub[1]

您正在告诉python将sub[1]复制到sub[0]中,因此对于python,您的新矢量将是:

sub <- [ reference_to_memory_where_sub1_is, sub1 ]

为了避免这种行为,您可以明确地告诉python在内存中复制对象。您可以使用模块";复制":

import copy
def switcher(y):
# shifts two characters
temp = y[0]
y[0] = y[1]
y[1] = temp
l1 = [1,2,3]
l2 = [1,2,3]
sub = [copy.deepcopy(l1),copy.deepcopy(l2)]
switcher(sub[0])
print(sub)
#[[2, 1, 3], [1, 2, 3]]
#restore
sub[0] = l1
print(sub)
# [[1, 2, 3], [1, 2, 3]]
switcher(sub[0])
print(sub)
#[[2, 1, 3], [2, 1, 3]]

相关内容

  • 没有找到相关文章

最新更新