7
myVar = ["jhhj", "hgc"]
myTuple = ([1,2,3], [4,5,6], myVar)
myVar.append('lololol')
print myTuple

为什么以及如何通过在构造后追加来修改这个元组?

myVar = "lol"
myTuple = ([1,2,3], [4,5,6], myVar)
myVar = "lolol"
print myTuple

为什么这会打印出来([1,2,3], [4,5,6], "lol")而不是([1,2,3], [4,5,6], "lolol")

4

6 回答 6

7

好吧,让我尝试用一​​些图像来解释。

在 Python 中,一切都是对象。这些对象由变量引用。某些类型的对象,例如列表和元组,只是存储对其他对象的引用。

也就是说,当你执行

myVar = ["jhhj", "hgc"]
myTuple = ([1,2,3], [4,5,6], myVar)

您或多或少会遇到这种情况:

一个指向三个列表的元组; 指向两个字符串的列表

每个对象都由一个框/矩形表示。我们有两个字符串对象,"jhhj""hgc"。此外,我们有一个由变量指向的列表对象myVar;此列表对象指向两个字符串对象。此外,我们有一个元组对象,由myTuple;引用。这个元组对象指向另外两个列表和引用的列表myVar

当你执行

myVar.append('lololol')

会发生什么?好吧,列表对象(由 偶然指向myVar)开始引用另一个值,即字符串对象"lololol"

一个指向三个列表的元组; 指向两个字符串的列表; 一个新的字符串被添加到列表中

请注意,myVar仍然引用列表对象。发生的事情是列表对象发生了变化。您可以从元组或从元组查看此列表对象myVar,您将看到具有相同更改的相同对象。

OTOH,当你执行

myVar = "lol"
myTuple = ([1,2,3], [4,5,6], myVar)

你会得到这样的东西:

一个指向两个列表和一个字符串的元组,也由一个变量指向

现在myVar指向字符串 object "lol",并且元组在其第三个位置引用它。现在,如果你执行

myVar = "lolol"

您只是myVar在指向另一个对象。元组对象仍然像以前一样指向"lol"

一个指向两个列表的元组和一个字符串,也由一个变量指向。 该变量现在引用另一个字符串。

所以,如果你给一个变量赋予一个新值,它只会改变这个变量所指向的值。变量引用的先前值将仍然存在*,并且指向它的任何其他变量或对象将保持指向它。只是属性变量会改变。

PS:另外,我前段时间回答了一个模糊相关的问题。您可能会发现答案很有帮助。

* 除非它是由垃圾收集器收集的,但这是另一个漫长的历史。

于 2012-06-14T03:36:54.177 回答
5

python中的所有东西都是对象。

所以当你做你最初的任务时

myVar = "lol"

您正在给 myVar 对象“lol”的引用

然后创建一个元组。第三个槽中的这个元组引用了“lol”

然后创建一个新对象“lolol”并给 myVar 一个引用。元组保留其对“lol”的原始引用

于 2012-06-14T02:53:08.753 回答
1

元组是不可变的,但您可以将它们连接在一起,例如:

var a = (1, 2)
var b = a + (3, 4)
于 2012-06-14T02:55:13.947 回答
1

在这两种情况下,当您创建元组时,您正在复制对myvar当时任何对象的引用。

在第一种情况下,myvar是一个可变对象。您可以在对对象的引用存储在元组中之后更改对象。

在第二种情况下,myvar是一个不可变的字符串。你不能改变对象,但你可以改变myvar它本身所指的东西。不过,这不会改变元组中包含的对象。

于 2012-06-14T03:38:22.693 回答
1

其他答案中有一些重要的观点,我将不再重复,解释namesobjects之间的区别。我认为缺少的只是说明某些 Python 代码何时对名称进行操作以及何时对对象进行操作。

但是,您需要了解的关键是,唯一直接影响名称的是赋值语句[1]。赋值语句重新绑定名称以指向不同的对象。出现在任何其他上下文中的名称只是执行该代码行时名称绑定到的任何对象的简单表示。

让我们看看您的示例中的这一行:

myTuple = ([1,2,3], [4,5,6], myVar)

myTuple出现在赋值语句的左侧,所以名称 myTuple是在那里受到影响的。myVar另一方面,在表达式内部,因此绑定的对象 myVar是元组的第三个元素,而不是名称myVar

因此,名称 后面发生的任何事情myVar对元组都没有任何影响。但只要元组的第三个元素myVar引用同一个对象,更改该对象(通过其中一个myVar或元组)显然会影响您通过任一引用查看对象时获得的结果。


[1] 对于高级学习,def语句class也是“赋值语句”(它们创建一个函数或一个类,然后将其分配给名称)。

此外,像+=,*=等运算符有时是赋值语句,有时不是,具体取决于 LHS 上当前名称所指对象的类型:

myList = []
myList += ['this calls a method on a list object which mutates it in place; the name is not changed']

myInt = 1
myInt += 10  # This rebinds myInt to refer to a new object 11; the object 1 is not changed
于 2012-06-14T04:31:00.500 回答
1

元组是不可变的,所以如果你想修改它的一个成员,你需要构造一个新的元组......

于 2012-06-14T02:52:23.357 回答