简体   繁体   English

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

[英]Function is changing both lists instead of one list based on '0' in Python

I'm a bit confused about why both outputs get changed after the restore when surely it should be just one(outputs are illustrated in the notes).我有点困惑为什么在恢复后两个输出都被更改,而它肯定应该只是一个(输出在注释中说明)。 Surely just the first one should change?当然只有第一个应该改变? If anyone could give me a suggestion as to why this happens I'd appreciate it如果有人能给我一个关于为什么会发生这种情况的建议,我将不胜感激

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]]

With sub[0] = sub[1] you are defining both lists to be the same object, that's why the subsequent change is applied to both of them.使用sub[0] = sub[1]您将两个列表定义为同一个对象,这就是为什么对它们都应用后续更改的原因。 Do sub[0] = sub[1][:] to create a copy, for example (there is more ways of doing this for a list).例如,执行sub[0] = sub[1][:]以创建副本(对于列表有更多方法可以执行此操作)。

When you are doing sub[0] = sub[1] , you are assigning the reference to the value at index 1 ie [1, 2, 3] in your case to index 0, so ultimately both the lists reside in the same memory location, and change in either makes the corresponding change to the other.当您执行sub[0] = sub[1] ,您将对索引1处的值的引用(即[1, 2, 3]在您的情况下)分配给索引 0,因此最终两个列表都驻留在同一内存中位置,并且其中任何一个的变化都会使另一个发生相应的变化。

You can verify this using id builtin which represents the memory reference for a given value:您可以使用id内置来验证这一点,它代表给定值的内存引用:

ids after initialization:初始化后的id:

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

ids after calling switcher:调用切换器后的 ID:

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

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

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

As you can see, the ids are same after assigning sub[0] = sub[1] , both the sub-lists get changed when modifying one of them如您所见,分配sub[0] = sub[1]后,id 相同,修改其中一个子列表时,两个子列表都会更改

The offending line is the assignment违规行是分配

sub[0] = sub[1]

Assignment never copies data.分配从不复制数据。

You are telling Python that the references sub[0] and sub[1] now both point to the same list object in memory (with the content [1,2,3] ).您告诉 Python 引用sub[0]sub[1]现在都指向内存中的同一个列表对象(内容为[1,2,3] )。

In your specific case this is easily fixed by taking a (shallow) copy of the list on the right hand side of the assignment.在您的特定情况下,这可以通过获取作业右侧列表的(浅)副本轻松解决。

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

You have a problem with references.你的引用有问题。 By defining:通过定义:

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

you create a list of two different list, but when you do:您创建了两个不同列表的列表,但是当您这样做时:

sub[0] = sub[1]

you are telling python to copy sub[1] into sub[0] hence for python your new vector will be:您告诉 python 将 sub[1] 复制到 sub[0] 中,因此对于 python,您的新向量将是:

sub <- [ reference_to_memory_where_sub1_is, sub1 ]

To avoid this behaviour you can explicitly tell python to duplicate the objects in memory.为了避免这种行为,您可以明确告诉 python 复制内存中的对象。 You can do this with the module "copy":你可以用模块“copy”来做到这一点:

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]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM