字典赋值是否导致指向Python中的同一对象?

Zub*_*ami 2 python dictionary

在Python中实现一些设计模式时,我发现了一些关于字典的有趣内容.我dict1用dict构造函数创建了一个变量.然后dict1被分配到dict2.但是当改变键的值时dict2,它会受到影响dict1.

码:

dict1 = dict(a=1, b=2)
dict2 = dict1
print("dict1 = ", dict1)
print("dict2 = ", dict2)

# assigning value of key 'a' in dict2 only
dict2['a'] = 0
print("---------------------------")
print("dict1 = ", dict1)
print("dict2 = ", dict2)
Run Code Online (Sandbox Code Playgroud)

输出:

dict1 =  {'b': 2, 'a': 1}
dict2 =  {'b': 2, 'a': 1}
---------------------------
dict1 =  {'b': 2, 'a': 0}
dict2 =  {'b': 2, 'a': 0}
Run Code Online (Sandbox Code Playgroud)

我发现列表也有相同类型的行为:

list1 = [1, 2, 3]
list2 = list1
print(list1, list2)
print("---------------------------")
list2.append(4)
print(list1, list2)
Run Code Online (Sandbox Code Playgroud)

输出:

[1, 2, 3] [1, 2, 3]
---------------------------
[1, 2, 3, 4] [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

但不是字符串:

str1 = "Good"
str2 = str1
print(str1, ",", str2)
print("---------------------------")
str2+=" thing"
print(str1, ",", str2)
Run Code Online (Sandbox Code Playgroud)

输出:

Good , Good
---------------------------
Good , Good thing
Run Code Online (Sandbox Code Playgroud)

很明显,字典和列表赋值与字符串赋值不同.但它是如何工作的?我正在寻找一些解释或相关资源.谁能帮我吗 ?提前致谢.

tim*_*geb 5

  1. Python知道名称和值.
  2. 当你这样做时x = something,x是值的新名称something.
  3. 分配永远不会复制数据.

考虑到这一点,让我们回顾一下这两个例子:

当你这样做

dict2 = dict1
Run Code Online (Sandbox Code Playgroud)

dict2是字典的新名称{'a':1, 'b':2} ,也有名称dict1.所有名称都可以看到对字典的所有更改!

当你这样做

str2 += " thing"
Run Code Online (Sandbox Code Playgroud)

你将名称重新绑定str2到结果str2 + " thing".您正在构建一个全新的字符串,并重新绑定该名称str2.str1str2现在不同的字符串名称和str1仍然指向原始字符串.

要记住的最后一件事/陷阱:有时候,+=操作员可以欺骗你并且x += y会做其他事情x = x + y.

这是一个例子:

>>> x = [1, 2, 3]
>>> y = x
>>> x = x + [4, 5, 6]
>>> x
[1, 2, 3, 4, 5, 6]
>>> y
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

正如所料,当您这样做时x = x + [4, 5, 6],您构建一个新列表并重新绑定该名称x.y仍然指向旧列表.然而...

>>> x = [1, 2, 3]
>>> y = x
>>> x += [4, 5, 6]
>>> x
[1, 2, 3, 4, 5, 6]
>>> y
[1, 2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)

从概念上讲,这是出乎意料的

x += [4, 5, 6] 
Run Code Online (Sandbox Code Playgroud)

应该做同样的事情

x = x + [4, 5, 6]
Run Code Online (Sandbox Code Playgroud)

什么情况是,当您使用+=您呼叫__iadd__x,即发生的事情是x.__iadd__([4, 5, 6]).

在列表的情况下,__iadd__ 扩展列表而不是构建新的列表对象,所以x += [4, 5, 6]相当于

x.extend([4, 5, 6]) 
Run Code Online (Sandbox Code Playgroud)

然后回来x.字符串在使用时表现如预期+=,即构建新字符串并重新分配名称.