Python 为什么函数修改列表不';在主文件中看到时是否不更改?
上下文:我需要随机删除一些数字列表中的精确元素,提取一些随机索引并将它们保存在一个名为aleaindex的集合中(完成后,由于一些SO用户的帮助,它正常工作)。现在,我想用新的、最终更短的列表newa、newb等替换旧的列表a、b等。下面是函数: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(..., ...)) ...
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[:]