Python 为什么函数修改列表不';在主文件中看到时是否不更改?

Python 为什么函数修改列表不';在主文件中看到时是否不更改?,python,list,function,Python,List,Function,上下文:我需要随机删除一些数字列表中的精确元素,提取一些随机索引并将它们保存在一个名为aleaindex的集合中(完成后,由于一些SO用户的帮助,它正常工作)。现在,我想用新的、最终更短的列表newa、newb等替换旧的列表a、b等。下面是函数: def myfunction(N, other_parameters, a, b, c): ... while (...): aleaindex.add(random.randint(..., ...)) ...

上下文:我需要随机删除一些数字列表中的精确元素,提取一些随机索引并将它们保存在一个名为aleaindex的集合中(完成后,由于一些SO用户的帮助,它正常工作)。现在,我想用新的、最终更短的列表newa、newb等替换旧的列表a、b等。下面是函数:

def myfunction(N, other_parameters, a, b, c):
    ...
    while (...):
        aleaindex.add(random.randint(..., ...))
    ...
    new_a = [v for i, v in enumerate(a) if i not in aleaindex]
    while a: a.pop()
        a = new_a[:]
    ...
对于其他列表b、c等,依此类推

问题:功能似乎在模块内正确修改了它们(通过打印检查),但当我在模块外(即“主”文件中)打印修改后的列表时,列表与未修改的列表相同。我哪里错了?

这一行:

a=new_a[:]
用新对象覆盖变量
a
。在函数或模块之外,旧对象仍然由
a
(或在那里调用的任何对象)指向。尝试:

解释 要了解这一点,请尝试以下方法

>>> a = [1,2,3,4]
>>> b = a
>>> print b
[1, 2, 3, 4]
>>> a[:] = [2,3]
>>> print b
[2, 3]
>>> a = [5]
>>> print b
[2, 3]
函数中的示例! 如果变量是可变的(并且正常列表是可变的),则以下操作有效:

>>> def f(a):
...     a[0] = 2
>>> b = [3]
>>> f(b)
>>> print b
[2]

变量不按值传递-您可以编辑可变值。

您发布的代码中没有函数。我怀疑问题在于您没有返回新值

您的代码可能会执行以下操作:

a = "foo"

def func():
    a = "bar" # uh-oh this not the same as the global a

func()
此时,全局
a
保持不变,因为
a
本地到
func
的变量不同

您要执行以下操作:

a = "foo"

def func():
    return "bar"

a = func()

该代码分配给全局范围内的
a
,并对其进行更改。

我不知道您想做什么,但从您的代码片段中,您显然丢失了。您的代码没有多大意义,并且存在不止一个问题。尽管如此,您所问的问题-为什么列表没有完全更改似乎与此循环有关:

while a: a.pop()
    a = new_a[:]
假设我们这样调用函数:

list1 = [1, 2, 3, 4, 5, 6, 7]
myfunction(N, other_parameters, list1, [], [])
当您调用第一行时,将得到一个名为
list1
的变量,它将指向一个列表:

调用函数
myfunction()
时,函数会创建一个名为
a
的变量,该变量将指向由
list1
指向的同一列表:

到目前为止,一切顺利。然后我们得到下面的循环:

while a:
    a.pop()
    a = new_a[:]
在它的第一行(
a.pop()
),您从列表中获得一个项目。由于变量
a
list1
都指向同一个列表,因此您将看到相同的结果

…如果不是循环的下一行(
a=new_a[:]
)。在这一行中,您将
设置为一个
变量,以指向另一个列表:

现在,您在
a
上执行的每个操作都将在此列表中,它与
list1
没有任何关系。例如,您可以在下一次迭代中执行
a.pop()
,以获得它:

但是,这毫无意义,因为行
a=new_a[:]
将再次替换指向另一个不同列表的
a


那么,解决方案是什么?我不知道。正如我所说的,不可能(至少对我来说)从您的代码中理解。您必须更多地思考您正在尝试做的事情,并向我们解释它,并提供更多的上下文。

您发布的代码中没有函数。对不起,我忘了说我发布的代码行在函数中!函数不返回任何内容,它应该只修改列表。以前版本的函数(我没有放这些行)运行正常(即列表也在模块外修改)。看,只需发布足够的代码来演示问题、错误的输出和所需的输出。好吧,告诉我这是否足够:我只是避免写很多东西,比如while循环的条件或者我输入到aleaindex集合中的值(这些部分工作得很好)。感谢如果您的问题似乎是关于函数之外发生了什么,我想说这是不够的。如果足够的话,那么可能用不同的词来表达你的问题。将代码、输入和输出视为问题的主要元素,将文本视为(完全必要但不充分的)支持元素。它用一个新对象覆盖同一变量。挑剔,
a[:]=new_a[:]
可以是
a[:]=new_a
。好的@Henry,多亏了你的帮助,我成功地获得了我想要的东西。只是,我不得不把一个[:]=new_a[:]放在循环之外。再次感谢您(以及其他人)的帮助
a[:]=new_a[:]
a[:]=new_a
相同,但与(3)
a=new_a[:]
不同,后者又不同于(4)
a=new_a
。前两个修改当前在
a
中的对象,使其具有与
new\u a
相同的内容。第二个两行将一个新对象分配给
a
,这可能是您想要的。在函数的前几行中,我只使用append和insert修改了列表,这也适用于全局,这可能误导了我(我刚刚开始用Python编写)?我应该如何返回一些列表并将全局列表分配给相应的本地版本?谢谢大家!@奥索我很高兴你这么说,因为这意味着你走对了方向。如果使用
a.append(1)
修改列表,则不是修改变量,而是修改变量引用的对象。无论使用什么变量访问特定对象,都会得到相同的对象,并进行相同的修改。如果你做了
a=[1]
你正在改变
a
所指的对象。太好了,我开始明白了!再次感谢你,@Marcin!首先,谢谢你非常有趣的回答,我正在饶有兴趣地阅读。不要责怪我没有展示太多代码,我只是觉得让问题变得像po一样一般更好
while a:
    a.pop()
    a = new_a[:]