据我所知,当您执行字典的浅表副本时,实际上会复制引用。所以,如果我这样做:
x={'key':['a','b','c']}
y=x.copy()
因此列表['a','b','c']的引用被复制到y中。每当我更改列表(例如x['key'].remove('a')
)时,dict x和y都会改变。这一部分我明白了。但是当我考虑下面的情况时:
x={'user':'admin','key':['a','b','c']}
y=x.copy()
当我执行y['user']='guest'
时,x ['user']不会更改,但列表仍然共享相同的引用。
所以我的问题是什么使字符串不同于列表?这背后的机制是什么?
答案 0 :(得分:14)
你做了两件不同的事情。当你这样做
x['key'].remove('a')
你改变x['key']
引用的对象。如果另一个变量引用同一个对象,您也会从该角度看到更改:
然而,在第二种情况下,情况有所不同:
如果你这样做
y['user']='guest'
你重新绑定 y['user']
到一个新对象。这当然不会影响x['user']
或它引用的对象。
顺便说一句,这与可变对象和不可变对象无关。如果你做了
x['key'] = [1,2,3]
你也不会改变y['key']
:
在PythonTutor.com上以交互方式查看。
答案 1 :(得分:5)
不同之处在于,在一种情况下,您要为字典键分配新值,而在另一种情况下,您正在修改现有值。请注意两段代码的区别:
x['key'].remove('a')
此处没有=
标志。你没有在字典中分配任何东西。事实上,这本词典甚至“不知道”发生了什么。你只是进入并操纵字典中的一个对象。
y['user'] = 'guest'
在这里,您实际上是为字典键分配了一个新值。
在第二种情况下,您无法执行等效的remove
,因为字符串是不可变的。但是,差异不是“因为字符串是不可变的”。区别在于你正在改变列表而不是字符串。您可以通过执行
x['key'] = ['new', 'list']
这会为x
中的密钥分配一个新值,使y
不受影响。