python 字典覆盖

今天写代码遇到一个字典更新的问题。
直接上代码:

# coding:utf-8

import collections
import numpy as np
a = np.array(([1, 2], [3, 4]))
b = collections.OrderedDict()
c = collections.OrderedDict()
for i in range(a.shape[0]):
    b['x'] = a[i][0]
    b['y'] = a[i][1]
    c[str(i)] = b
for key,value in c.items():
    print(key, value)

打印结果居然是:

0 OrderedDict([('x', 3), ('y', 4)])
1 OrderedDict([('x', 3), ('y', 4)])

这个现象很神奇,就是说明明写了一个c字典,正常情况下应该输出的是:

0 OrderedDict([('x', 1), ('y', 2)])
1 OrderedDict([('x', 3), ('y', 4)])

研究了半天,真是没有头绪。
后来查了一下,终于明白python中一切皆引用,也就意味着,当将b赋值给c的时候,其实不是真正的赋值操作,而是将b的地址给了c,那么当b在第二次循环的时候,b中的内容发生了改变,那么c中之前赋值操作的内容也会发生改变。最好的方式就是直接打印出地址看一下就好了:

# coding:utf-8

import collections
import numpy as np
a = np.array(([1, 2], [3, 4]))
c = collections.OrderedDict()
b = collections.OrderedDict()
for i in range(a.shape[0]):
    b['x'] = a[i][0]
    b['y'] = a[i][1]
    c[str(i)] = b
    print(id(b), id(c[str(i)]))

得到的地址是:

2304502297544 2304502297544
2304502297544 2304502297544

也就是说,c中的两个键都存的是b的地址,所以,其实折腾来折腾去其实是对同一块内存的修改。

这里其实有两个问题:

  1. 如果用全局变量,那么用b的深拷贝。
  2. b应该作为局部变量进行赋值

用b的深拷贝

import collections
import numpy as np
a = np.array(([1, 2], [3, 4], [5,6],[7, 8]))
c = collections.OrderedDict()
b = collections.OrderedDict()
for i in range(a.shape[0]):
    b['x'] = a[i][0]
    b['y'] = a[i][1]
    c[str(i)] = b.copy()
print(id(b), id(c[str(0)]), id(b), id(c[str(1)]))
for key,value in c.items():
    print(id(c[key]))
    print(key, value)

地址和输出如下:

2433414755272 2433414755400 2433414755272 2433414755528

2433414755400
0 OrderedDict([('x', 1), ('y', 2)])
2433414755528
1 OrderedDict([('x', 3), ('y', 4)])

可以看到,c的两个内容地址是不一样的,而且也与b不一样。这个过程就是每次循环都真正生成了另外一个对象来存储b中的内容,这样即使b发生了改变,另外一个对象也不会发生改变,因为两者是不同的对象。

将b换做局部变量

import collections
import numpy as np
a = np.array(([1, 2], [3, 4]))
c = collections.OrderedDict()

for i in range(a.shape[0]):
    b = collections.OrderedDict()
    b['x'] = a[i][0]
    b['y'] = a[i][1]
    c[str(i)] = b
for key,value in c.items():
    print(id(c[key]))
    print(key, value)

输出如下:

2487731450824
0 OrderedDict([('x', 1), ('y', 2)])
2487731450952
1 OrderedDict([('x', 3), ('y', 4)])

可以看到,每次的b都是不同的,因此c中保存的内容也是不同的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值