# 代码一
list1 = []
dict1 = {}
for i in range(5):
dict1 = {"one": i}
list1.append(dict1)
print(list1) # [{‘one‘: 0}, {‘one‘: 1}, {‘one‘: 2}, {‘one‘: 3}, {‘one‘: 4}]
# 看一下列表的id值
for id_value in map(lambda x: id(x), list1):
print(id_value)
我的理解
循环外部创建了一个空的字典和一个变量并进行赋值。我们知道在 Python 中,对象赋值实际上是对象的引用即,一个变量给另一个变量赋值时,传的是地址,所以就将dict1这个变量和{}这个空字典捆绑在了一起,或者说dict1指向了{}
for循环内每次字典的创建{"one": i}都会在内存中新开辟一块空间用来存放该字典,而每次的赋值操作又会将dict1这个变量指向新的字典如{"one":0}
然后对list1进行append操作时,我的猜想(已证实)是进行 append 操作时,实际上追加的是该对象的引用,因此每次append时都会将每个字典的(引用)内存地址传入list1
查看一下list1的 id (它可以返回对象的唯一标识) [‘1593305955784‘,‘1593305955496‘,‘1593306802432‘...],注意里面的 id 并不相同
列表中包含各个不同字典的内存地址,因此最终生成的列表就是各个值都不相同的列表
?
?
?
# 代码二
list2 = []
dict2 = {}
for i in range(5):
dict2["one"] = i
print(dict2) # 依次输出 {‘one‘: 0},{‘one‘: 1},{‘one‘: 2},{‘one‘: 3},{‘one‘: 4}
list2.append(dict2)
print(list2) # [{‘one‘: 4}, {‘one‘: 4}, {‘one‘: 4}, {‘one‘: 4}, {‘one‘: 4}]
# 看一下列表的id值
for id_value in map(lambda x: id(x), list1):
print(id_value)
我的理解
根据输出可以看出,dict2["one"] = i每一次都只是对字典dict2进行修改,最后保留了最后修改的结果,并没有像 代码一 那样新建一个字典
试着分析一下过程
先在内存中开一块区域放空字典并赋值给dict2(引用)
?
每次循环都修改dict2所指向的那块区域
?
之后将dict2所指向的内存中的字典的内存地址 append 至list2中
?
但是每一次的dict2["one"] = i并没有新建字典,始终是在对该字典的value进行重写,并没有新建字典,自始至终只有一个字典,所以每次append的都是同一个内存地址
?
我们可以用来查看一下这个列表的 id, [‘2966419766368‘,‘2966419766368‘,‘2966419766368‘...],发现id 都是一样的
?
因为由于一个key只能对应一个value,多次对一个key放入value,后面的值会把前面的值覆盖掉,因此最终list2的值就以最后一次修改字典的值为准。列表中包含同一个的内存地址,因此最终生成的列表就是各个值都相同的列表
?
浅拷贝只拷贝了对象的引用,遇上这种情况可以深拷贝解决
?
?
以上内容仅代表个人看法,不具有权威性,看看就好...
原文:https://www.cnblogs.com/NoTrace/p/12580652.html