问题描述
我有一个关于列表可变性的问题。我目前正在阅读 YouTuber/程序员 senddex 的教程,出现的问题之一是对象和列表的可变性与不变性。
示例 1:
x = [1]
print(id(x))
def test():
x = [2]
test()
print(x)
print(id(x))
在这个例子中,x 仍然是 [1]。
示例 2:
x = [1]
print(x)
print(id(x))
def test():
x [0]= 2
test()
print(x)
print(id(x))
在本例中,x 更改为 [2]。
所以我的问题是,列表是否仅在通过特定函数内的索引值更改列表时才可变?
感谢您的帮助!
解决方法
“可变”意味着您可以更改对象内的特定元素。对于非可变对象,如果您想为特定元素使用不同的值,则必须重新分配整个对象。列表始终具有更改特定元素的能力。在你的第二个例子中,列表仍然是可变的,但你没有改变它。您正在重新分配它。
在 Python 中,当一个函数被调用时,默认行为是所有变量名称的作用域都在函数内,但该函数可以完全访问对象。当您编写 x[0] = 2
时,您正在访问实际对象,并更改该对象的第一个元素。当你写 x = [2]
时,你不再处理同一个对象,你只处理 name "x" 和 name 的作用域em> 仅在函数内。但是,如果您在函数中编写了 global x
,那么这将告诉 Python 您希望名称“x”具有全局作用域,并且它会将名称“x”重新分配给新对象 {{1} } 对于整个程序。然后,您会在主程序中看到 [2]
和 x[0]
的不同值。
这是一件相当难解释的事情,因为问题在于对象名称与该名称所指对象之间的区别,并且很难在不使用名称的情况下谈论对象。我不知道这是否使事情更清楚或更混乱,但假设我们将第一个列表称为 object1,将第二个列表称为 object2(也就是说,我们会假装如果您取第一个对象的 id,得到1,如果你取第二个的id,你得到2)。当您调用 id(x)
时,您将传递名称为“x”的 object1。如果您有 test
行,则您正在创建 object2,将值 x=[2]
放入其中,并告诉 Python 在函数 2
中,名称 test
指向对象 2。另一方面,如果您有 x
行,则您仍在处理 object1,并将其第一个元素的值更改为 x[0]=2
。