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

  • 查看一下list1id (它可以返回对象的唯一标识) ['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的值就以最后一次修改字典的值为准。列表中包含同一个的内存地址,因此最终生成的列表就是各个值都相同的列表

 
浅拷贝只拷贝了对象的引用,遇上这种情况可以深拷贝解决
 
 
以上内容仅代表个人看法,不具有权威性,看看就好...

posted @ 2020-03-27 12:55  未月之四  阅读(277)  评论(0编辑  收藏  举报