为什么功能修改列表在主文件中看不到时会改变?

时间:2013-06-01 14:17:08

标签: python list function

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

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 等。

问题:该函数似乎在模块中正确修改它们(通过打印检查)但是,当我打印修改后的列表模块外面时,就是“主”文件,列表是他们没有修改过的。我哪里错了?

3 个答案:

答案 0 :(得分:8)

这一行:

a=new_a[:]

用新对象覆盖变量a。在函数或模块之外,a(或者在那里调用的任何东西)仍指向旧对象。尝试:

new_a = [v for i, v in enumerate(a) if i not in aleaindex]
while a:
    a.pop()
    a[:] = new_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]

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

答案 1 :(得分:2)

我不知道你想要做什么但是从你的片段中你显然已经失去了。您的代码没有多大意义,并且存在多个问题。尽管如此,你问的问题是 - 为什么列表没有完全改变? - 似乎与这个循环有关:<​​/ p>

while a: a.pop()
    a = new_a[:]

假设我们以这种方式调用你的函数:

list1 = [1, 2, 3, 4, 5, 6, 7]
myfunction(N, other_parameters, list1, [], [])

当您拨打第一行时,您将获得一个名为list1的变量,它将指向一个列表:

list1 points to a list

当您调用函数myfunction()时,该函数除其他外,还会创建一个名为a的变量,该变量将指向list1指向的相同列表:

Now a points to the same list as list1

到目前为止,这么好。然后我们进入下面的循环:

while a:
    a.pop()
    a = new_a[:]

在第一行(a.pop())中,您可以从列表中获取一个项目。由于变量alist1都指向同一个列表,因此您会看到相同的结果......

Removing an item from the list

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

a points to another list

现在,您在a上执行的每项操作都将出现在此列表中,该列表与list1无关。例如,您可以在下一次迭代中执行a.pop()来获取它:

Popping from the other list

然而,它完全没有意义,因为行a = new_a[:]将替换再次指向的列表 另一个不同的列表 >:

Changing a again?!

那么,解决方案是什么?我不知道。正如我所说的那样,(至少对我来说)不可能从你的代码中理解。你必须更多地反思你正在尝试做什么,并向我们解释一下,还有更多的背景。

答案 2 :(得分:1)

您发布的代码中没有任何功能。我怀疑问题是你没有返回新值。

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

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,并进行更改。