1

我对为什么会发生以下情况感到非常震惊:

这是我的代码:


def add_one(array):

    new_array = array
    length = len(array)

    for i in range(length):

        new_array[i] = new_array[i]+1


    return new_array

x = [1,2,3,4,5];
y = add_one(x)

print x

print y

结果如下:

[2, 3, 4, 5, 6]

[2, 3, 4, 5, 6]

我不明白为什么 x 会改变。

我的猜测:不知何故,x 是作为函数 add_one 的全局变量。我包括了'new_array = array',这样如果array 是某种全局变量x,x 就不会改变。然而,当执行 'new_array = array' 时,不知何故 new_array 也变成了全局变量 x。我写了函数 add_one 的另一个版本,它没有给我带来问题:


def add_one(array):

    new_array = []
    length = len(array)

    for i in range(length):
        new_array.append(array[i]+1)

似乎如果一个局部变量(即一个数组)通过它在函数中的索引进行编辑,那么它相对于作为该函数输入的全局变量变成全局变量?

我不知道发生了什么。任何解释将不胜感激。

4

4 回答 4

6

当您说 时new_array = array,您不是在制作数组的副本,而只是在为数组制作另一个名称。这两个名称仍然适用于同一个数组。

制作副本最简单的方法是使用切片:new_array = array[:]

于 2011-04-20T21:58:56.043 回答
4

对于晦涩的阅读,没有什么是全局的。array仍然是一个完全正常的局部变量。但它是一个参考,因为 Python 中的所有内容(至少每个名称)都是一个参考:

  • add_one(x)将引用(不像 C++ 中的引用,更像是指针 - 如果其中任何一个对您意味着什么xadd_one
  • new_array = array只会复制该参考
  • 没有复制发生,所有这些名称都指向同一个对象!

这意味着arrayadd_one修改了x调用者引用的相同对象上调用方法 - 重新分配array( array = []) 只会覆盖引用的本地副本,不会影响引用同一对象的其他变量(毕竟,这很有可能没有这样的变量!),但成员或项目分配(例如new_array[i] = ...)基本上是一个方法调用,并将修改对象。

通常,从现有列表生成新列表的最简单方法是使用列表推导式,并对每个元素应用一些修改模式并可选地进行一些过滤。[x + 1 for x array]在这个例子中。

于 2011-04-20T22:01:23.480 回答
1

在第三行,您将 y 设置为 x。

new_array = array
于 2011-04-20T21:59:37.107 回答
0

这一行是关键:

new_array = array

您必须new_array不将其视为新变量,而应将其视为已经具有名称的变量(对象)的新名称array

于 2011-04-20T21:56:43.833 回答