在我运行下面的代码之后,有人可以告诉我为什么这些是变量现在引用的值:
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)
答案 0 :(得分: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
因此,很明显原始id
的{{1}}与从函数返回的x
相同。但原始id
的{{1}}与返回的y
不同。
答案 1 :(得分:0)
简单。可变对象(如列表)通过引用传递,而不可变对象(如整数)通过值传递。
当您执行x1 = x
时,x1
会引用x
;因此,对x
的任何更改也适用于x1
,因为它们指的是同一个对象。 x.append(5)
通过引用更改原始x
,从而更改x1
。
但是,当您执行x2 = x[:]
时,您将通过切片来复制列表的内容。因此,您正在制作新列表。
执行y = y + [5]
时,您将在函数范围内创建新列表。因此,全局y
(和y1
引用)保持不变。 y2
只是原始y
的副本,因此该功能根本不会影响它。
答案 2 :(得分:0)
您实际上没有更改y的引用,只是将其设置为不同的引用。这实际上不会改变你传入的y。只是my_function的局部范围中的y。
逐步完成here
答案 3 :(得分:-1)
你实际上是在处理范围问题。起初看起来你会遇到别名问题,但是你传入的变量的重新定义只能在函数中持续存在。函数完成运行后,传入的参数(简单地说)将返回其原始值。只有在功能范围内,他们才会继续拥有您重新分配给它们的值。尝试在函数结束前打印奇数输出。