2

有人能告诉我为什么,在我运行下面的代码之后,这些是变量现在引用的值:

x = [1, 2, 3, 5] 
x1 = [1, 2, 3, 5] 
x2 = [1, 2, 3] 
y = [1, 2, 3] 
y1 = [1, 2, 3] 
y2 = [1, 2, 3]

为什么不是y = [1, 2, 3, 5]

为什么不是x1 = [1, 2, 3]

因为,遵循这个逻辑:

a = 1
b = a
a = 3
b is still equal to 1, not 3.

代码如下。谢谢你的帮助。

def my_function(x, y):
    x.append(5)
    y = y + [5]


x = [1, 2, 3]
x1 = x
x2 = x[:]


y = [1, 2, 3]
y1 = y
y2 = y[:]


my_function(x, y)
4

4 回答 4

5

该声明:

x1 = x

为 .所指向的同一个列表创建一个引用的副本x。现在您正在传递x给函数,在其中将值附加到x

x.append(5)

这会影响函数外原来指向的列表x,最终也会反映对x1. 因此x1[1, 2, 3, 5]


现在,在 的情况下y1,唯一的区别是函数中的这一行:

y = y + [5]

此行不会更改y函数外部引用的原始列表。它创建一个局部变量y,并将其初始化为[1, 2, 3, 5]. 但它不会更改y函数外部引用的原始列表,因此不会更改y1. 所以,y1仍然y[1, 2, 3]


您可以通过检查id函数内部的列表和外部的列表来验证它:

>>> def my_function(x, y):
...     x.append(5)
...     y = y + [5]
...     return x, y   
... 
>>> 
>>> x = [1, 2, 3]
>>> x1 = x
>>> y = [1, 2, 3]
>>> y1 = y
>>> 
>>> x2, y2 = my_function(x, y)
>>> 
>>> id(x2) == id(x)   
True
>>> id(y2) == id(y)
False

因此,很明显idoriginalx与从函数返回的相同。但id原件y和退货不一样y

于 2013-08-09T16:46:05.517 回答
0

简单的。可变对象(例如列表)通过引用传递,而不可变对象(例如整数)通过值传递。

当你做的时候x1 = xx1指的是x;所以任何更改x也适用于x1,因为它们指的是同一个对象x.append(5)更改原始x,因此x1通过引用。

但是,当您这样做时x2 = x[:],您将通过切片来复制列表的内容。因此,您正在制作一个列表。

当您这样做时y = y + [5],您将在函数的范围内创建一个新列表。因此,全局y(和y1通过引用)保持不变。y2只是原始的副本y,因此该功能也根本不会影响它。

于 2013-08-09T16:45:15.107 回答
0

您实际上并没有更改 y 的引用,只是将其设置为不同的引用。这实际上不会更改您传入的 y。只是 my_function 本地范围内的 y。

在这里逐步完成

于 2013-08-09T16:45:48.917 回答
-1

您实际上在这里处理的是范围问题。起初,您似乎遇到了别名问题,但是您对传入变量的重新定义仅在函数中持续存在。一旦函数运行完毕,传入的参数(简单地说)就会恢复到它们的原始值。只有在函数内,它们才会继续具有您重新分配给它们的值。尝试在函数结束之前打印奇数输出。

于 2013-08-09T16:48:46.747 回答