共享引用和相等性

3

我正在使用Python 3.4,并通过O'Reily出版的一本书中的示例进行学习。 这个例子展示了:

A = ['spam']
B = A
B[0] = 'shrubbery'

运行print A后的结果:
'shrubbery'

现在我思考的过程是A被定义但从未改变。
这个例子会得到不同的结果。
A = 'string'
B = A
B = 'dog'

这是运行print A后的结果:
'string'

请问能否解释一下?


关于 Python 内部内存模型的详细信息,我建议参考 Wesley Chun 的演示文稿 Understanding Python’s Memory Model & Mutability,他在 回答一个经典的 SO 问题 中提到了这个主题。特别是第9页及以后正好涉及到这个问题。 - zehnpaard
对于更倾向于视听的人,这里提供同一演示文稿的视频链接 - zehnpaard
6个回答

4
在第一个例子中,您正在修改B引用的列表。
执行:
B[0] = 'shrubbery'

告诉Python将B所引用的列表的第一个项目设置为'shrubbery'的值。此外,这个列表恰好是由A所引用的同一个列表。这是因为执行以下操作:

B = A

BA 指向同一个列表的原因:

>>> A = ['spam']
>>> B = A
>>> A is B
True
>>>

因此,对B所引用的列表所做的任何更改都将影响到A所引用的列表(反之亦然),因为它们是同一个对象。


然而,第二个示例并没有修改任何内容。相反,它仅仅将名称B重新分配给一个新值。

一旦执行了这条语句:

B = 'dog'

B不再引用字符串'string',而是引用新的字符串'dog'。同时,A的值保持不变。


0

可变对象是列表,而字符串是不可变的,这就是为什么你可以改变内存地址和列表本身,但不能改变字符串的原因。


0
我们在这里谈论共享引用和可变/不可变对象。当你执行B = A时,两个变量都指向同一个内存地址(共享引用)。 第一种情况,列表是可变对象(它的状态可以改变),但对象的内存地址保持不变。因此,如果您更改其状态,则另一个变量将看到这些更改,因为它指向相同的内存地址。(A和B具有相同的值,因为它们指向内存中的同一对象) 第二种情况,字符串是不可变的(您无法更改它)。通过执行B = 'dog',基本上您创建了另一个对象,现在B指向另一个对象(另一个内存地址)。在这种情况下,A仍然指向同一个旧的内存引用(A和B具有不同的值)

0

enter image description here

希望你能用这种方式理解它 :-)

正如你在第一种方法中看到的那样,它们都引用了同一个list,而第二种方法则不同。因此,在第二种方式中进行的更改不会影响另一个。


2
@NoMorePuppies 我认为这是一个很好的解释,但我也认为纯图形答案在 SO 上是不可接受的 - 它们无法搜索和重复,并且不符合辅助功能标准。 - Jivan

0

在大多数现代动态语言中,Python 中的变量实际上是引用,类似于 C 指针。这意味着当您执行像 A = B(其中 A 和 B 都是变量)这样的操作时,您只需使 A 指向与 B 相同的内存位置。

在第一个示例中,您正在就地更改(修改)现有对象 - 这就是 variable_name[index/key] = value 语法所做的事情。A 和 B 继续指向相同的东西,但是这个东西的第一个条目现在是 'shrubbery',而不是 'spam'。

在第二个示例中,当您说 B = 'dog' 时,您使 B 指向一个不同的(此时为新的)对象。


-2

以下是这两者之间的区别:

enter image description here

enter image description here

这是一步一步的分析:
A = ['spam']
"A points to a list whose first element, or A[0], is 'spam'."
B = A
"B points to what A points to, which is the same list."
B[0] = 'shrubbery'
"When we set B[0] to 'shrubbery', the result can be observed in the diagram.
A[0] is set to 'shrubbery' as well."
print (A):



A = 'string'
"A points to 'string'."
B = A
"B points to what A points to, which is 'string'."
B = 'dog'
"Oh look! B points to another string, 'dog', now.
So does what A points to change? No."
The result can be observed in the diagram.
print (A):

@kindall 请看看我的回答现在是否正确。感谢您指出这一点!我一直在想Java... - Jobs
措辞不当...让我做一些更正。@kindall - Jobs
左边是全局框架,就像环境图一样,右边是创建的对象。@kindall - Jobs
@kindall 我会添加一些澄清。 - Jobs
谢谢。希望现在更加清晰了。@Jivan - Jobs
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接