Python字典注意事项
# 代码一
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
的值就以最后一次修改字典的值为准。列表中包含同一个的内存地址,因此最终生成的列表就是各个值都相同的列表
- 先在内存中开一块区域放空字典并赋值给
浅拷贝只拷贝了对象的引用,遇上这种情况可以深拷贝解决
以上内容仅代表个人看法,不具有权威性,看看就好...