Python - 修改与覆盖对象引用

时间:2017-05-14 15:48:24

标签: python object-reference

有人可以通过易于理解的方式解释修改与覆盖对象引用吗?这是我的意思的一个例子:

修改对象引用:

nested_list = [[]]*3
nested

result:
[[], [], []]
# now let me **modify** the object reference
nested[1].append('zzz')

result:
[['zzz'], ['zzz'], ['zzz']]

通过覆盖对象引用:

nested_list = [[]]*3
nested

result:
[[], [], []]
# now let me **modify** the object reference
nested[1] = ['zzz']

result:
[[], ['zzz'], []]

这是否意味着在使用"追加"我们只是在使用赋值时修改对象引用,即

nested[1] = ['zzz']

我们是否覆盖了值并将嵌套[1]赋值给新的对象引用?是否由"追加"之间的潜在差异引起?方法和赋值?如果是这样的差异是什么?

2 个答案:

答案 0 :(得分:2)

让我们将名称x分配给一个空列表,以便更容易推理代码。

在你的第一个例子中

>>> x = []
>>> nested = [x]*3
>>> nested
[[], [], []]

您正在创建一个列表nested,其中包含对x的三个引用。这是证据:

>>> all(e is x for e in nested)
True

我们只创建了一个空列表x,这就是

的原因
nested[0].append('zzz')
nested[1].append('zzz')
nested[2].append('zzz')

x.append('zzz')

都是等效的,并将附加到内存中的相同列表

>>> nested[0].append('zzz')
>>> nested
[['zzz'], ['zzz'], ['zzz']]
>>> nested[1].append('zzz')
>>> nested
[['zzz', 'zzz'], ['zzz', 'zzz'], ['zzz', 'zzz']]
>>> nested[2].append('zzz')
>>> nested
[['zzz', 'zzz', 'zzz'], ['zzz', 'zzz', 'zzz'], ['zzz', 'zzz', 'zzz']]
>>> x.append('zzz')
>>> nested
[['zzz', 'zzz', 'zzz', 'zzz'], ['zzz', 'zzz', 'zzz', 'zzz'], ['zzz', 'zzz', 'zzz', 'zzz']]

第二个例子很简单。您创建一个列表nested,该列表最初包含对同一空列表的三个引用。

然后你覆盖 nested的第二个元素(即nested[1])通过发布

引用的内容
>>> x = []
>>> nested = [x]*3
>>> nested[1] = ['zzz']
>>> nested
[[], ['zzz'], []]

nested的第二个元素是一个与nested的第一个和第三个元素无关的新列表。

>>> nested[0] is nested[1]
False
>>> nested[2] is nested[1]
False
>>> nested[0] is nested[2]
True

由于您没有修改nested[0]nested[2]引用,因此它们仍然保持相同的空列表(在我们的示例中也使用名称x)。

>>> x.append('x')
>>> nested
[['x'], ['zzz'], ['x']]

答案 1 :(得分:1)

正如我在评论中写的那样,*上的list运算符只是复制了列表中的引用:

nested_list = [[]] * 3

nested_list内的所有三个元素都指向同一个列表。如果您考虑上面的表达式真正说出的内容,这是有道理的。评估确实按以下顺序进行:

nested_list = [[]]  # first create a list with an empty list.
nested_list = nested_list * 3  # duplicate the references to that empty list

到你问题的第二部分。如果用新列表替换第二个元素:

nested_list[1] = ['zzz']

第一个和第三个元素引用相同的空列表,但刚刚分配给(['zzz'])的元素是一个新列表(带有一个元素'zzz'。)

E.g。如果您执行以下操作,您将看到第一个和第三个仍然引用相同的列表:

nested_list[0].append('a')
print(nested_list)
# [['a'], ['zzz'], ['a']]

解决方案

要创建三个不同的空列表,这可能是您想要的,您通常会执行类似的操作(以下行是等效的):

nested_lists = [[] for _ in range(3)]
nested_lists = [[], [], []]