0

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

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[:]
    ...

对于其他列表bc等,依此类推。

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

4

3 回答 3

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]

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

于 2013-06-01T14:23:06.103 回答
2

我不知道您要做什么,但是从您的片段中您显然迷路了。您的代码没有多大意义,而且问题不止一个。尽管如此,你问的问题 - 为什么列表没有完全改变?- 似乎与这个循环有关:

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

假设我们这样调用你的函数:

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

会发生什么,当你调用第一行时,你会得到一个被调用的变量list1,它会指向一个列表:

list1 指向一个列表

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

现在 a 指向与 list1 相同的列表

到目前为止,一切都很好。然后我们进入下面的循环:

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

在它的第一行 ( a.pop()) 中,您从列表中获得了一个项目。由于变量alist1指向同一个列表,你会看到相同的结果......

从列表中删除项目

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

a 指向另一个列表

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

从另一个列表中弹出

但是,这根本没有意义,因为该行将替换再次a = new_a[:]指向另一个列表的列表a

又换了?!

那么,解决方案是什么?我不知道。正如我所说,(至少对我而言)从您的代码中理解是不可能的。您必须更多地反映您正在尝试做的事情并向我们解释,并提供更多背景信息。

于 2013-06-01T15:11:08.007 回答
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()

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

于 2013-06-01T14:23:08.350 回答