为什么复制的词典指向同一目录但列表却没有?

时间:2013-06-17 02:50:43

标签: python list dictionary

有人可以告诉我为什么当你复制词典时它们都指向同一个目录,所以改变一个会影响另一个,但这不是列表的情况吗?

我对他们为什么会单向设置字典并列出另一个字典的逻辑感兴趣。令人困惑,如果我知道其背后的原因,我可能会记得。

dict = {'Dog' : 'der Hund' , 'Cat' : 'die Katze' , 'Bird' : 'der Vogel'}
otherdict = dict
dict.clear()
print otherdict

其他结果是otherdict = {}。因此两个dicts都指向同一目录。但这不是列表的情况。

list = ['one' , 'two' , 'three']
newlist = list
list = list + ['four']
print newlist

新名单仍然保留在旧列表中。所以他们没有指向同一个目录。我想知道它们不同的原因背后的理由吗?

4 个答案:

答案 0 :(得分:4)

某些与您的意图相似的代码会显示对一个列表的更改会影响其他引用。

>>> list = ['one' , 'two' , 'three']
>>> newlist = list
>>> list.append('four')
>>> print newlist
['one', 'two', 'three', 'four']

这是与你的字典代码最接近的类比。您在原始对象上调用方法。

与您的代码不同的是,您使用了单独的加号和赋值运算符

list = list + ['four']

这是两个单独的操作。首先,解释器评估表达式list + ['four']必须将该计算的结果放在新的列表对象中,因为它不会预期您将结果返回到列表。如果您说other_list = list + ['four'],如果列表被修改,您会非常恼火。

现在有一个新对象,其中包含list + ['four']的结果。该新对象已分配给列表。 list现在是对新对象的引用,而newlist仍然是对旧对象的引用。

即使这是不同的

list += ['four']

+ =具有可变对象的含义,它将修改对象。

答案 1 :(得分:4)

你的两个案例对你正在复制的对象做了不同的事情,这就是你看到不同结果的原因。

首先,你并没有真正复制它们。您只需制作新的“引用”或(以更多Pythonic术语)将新名称绑定到相同的对象。

使用字典,您正在调用dict.clear,它会丢弃所有内容。这会修改现有对象,因此您可以通过两个引用来查看结果。

使用该列表,您将其中一个名称重新绑定到新列表。这个新列表与旧列表不同,旧列表仍未修改。

如果需要,您可以使用列表重新创建字典代码的行为。切片分配是一次修改整个列表的一种方法:

old_list[:] = [] # empties the list in place

与上述主要问题无关的一个附录:在您自己的代码中使用dictlist等名称作为变量是一个非常糟糕的主意。那是因为那些是内置Python字典和列表类型的名称。通过使用相同的名称,您可以隐藏内置的名称,这可能会导致混乱的错误。

答案 2 :(得分:3)

在您的字典示例中,您创建了一个字典并将其存储在dict中。然后,您在otherdict中存储相同的引用。现在, dictotherdict都指向相同的字典 *。然后你拨打dict.clear()。这会清除dictotherdict指向的字典。

在列表示例中,您已创建了一个列表并将其存储在list中。然后,您在otherlist中存储相同的引用。 然后您创建一个新列表,其中包含list元素和另一个元素,存储列表在{{1}中}。您没有修改您创建的原始列表。您创建了一个新列表并更改了list指向的内容。

您可以使用list而不是list.append('four')来获取列表示例以显示与字典示例相同的行为。

答案 3 :(得分:1)

你是说这个吗?

>>> d = {'test1': 1, 'test2': 2}
>>> new_d = d
>>> new_d['test3'] = 3
>>> new_d
{'test1': 1, 'test3': 3, 'test2': 2}
>>> d # copied over
{'test1': 1, 'test3': 3, 'test2': 2}
>>> lst = [1, 2, 3]
>>> new_lst = lst
>>> new_lst.append(5)
>>> new_lst
[1, 2, 3, 5]
>>> lst # copied over
[1, 2, 3, 5]
>>> new_lst += [5]
>>> lst # copied over
[1, 2, 3, 5, 5]
>>> my_tuple = (1, 2, 3)
>>> new_my_tuple = my_tuple
>>> new_my_tuple += (5,)
>>> new_my_tuple
(1, 2, 3, 5)
>>> my_tuple # immutable, so it is not affected by new_my_tuple
(1, 2, 3)

列表DO传递引用,而不是对象本身。大多数(犹豫不决)可变(可以改变,如列表和字典)对象传递引用,而不可变(不能更改,如元组)对象自己传递对象。