为何将NumPy数组存入字典后多变量指向同一内存块?
问题解答
这是Python里的预期现象,你的操作确实有问题——直接用=赋值字典或numpy数组这类可变对象时,只是让新变量指向原对象的引用,不是创建独立的副本,所以三个变量最终都指向同一个字典和里面的numpy数组。
原因说明
Python中,字典、列表、numpy数组都是可变对象,赋值操作a = b不会复制整个对象,只是把a变成b的一个"别名",两者共享同一块内存里的数据。比如你执行probabilities = bins后,probabilities和bins其实是同一个字典,修改probabilities里的数组,本质上就是修改bins里的数组;后续cumulativeDistributionFunction = probabilities同理,又多了一个指向同一字典的别名。
解决方法
要得到三个独立的变量,需要对字典和里面的numpy数组做深拷贝,确保每个层级的对象都是新的。有两种常用方式:
方式1:用copy.deepcopy(最省心)
导入copy模块后,直接对整个字典做深拷贝,它会递归复制所有嵌套的可变对象(包括里面的numpy数组):
import numpy as np import copy # 初始化bins bins = { "Number 1": np.zeros(50, dtype=int), "Number 2": np.zeros(50, dtype=int), "Number 3": np.zeros(50, dtype=int), "Number 4": np.zeros(50, dtype=int), "Number 5": np.zeros(50, dtype=int)} # 填充bins数据 for index, key in enumerate(bins.keys()): for numberDrawn in dataset[:, index]: bins[key][numberDrawn-1] += 1 # 深拷贝得到独立的probabilities probabilities = copy.deepcopy(bins) for key in probabilities.keys(): probabilities[key] = probabilities[key]/probabilities[key].sum() # 深拷贝得到独立的cumulativeDistributionFunction cumulativeDistributionFunction = copy.deepcopy(probabilities) for key in cumulativeDistributionFunction: for index, x in enumerate(cumulativeDistributionFunction[key]): if index == 0: continue else: cumulativeDistributionFunction[key][index] += cumulativeDistributionFunction[key][index-1]
方式2:手动遍历拷贝(更灵活)
因为字典里的元素都是numpy数组,也可以手动遍历字典,对每个数组调用.copy()方法创建独立副本:
import numpy as np # 初始化bins和填充数据部分同上... # 手动拷贝字典和数组 probabilities = {k: v.copy() for k, v in bins.items()} for key in probabilities.keys(): probabilities[key] = probabilities[key]/probabilities[key].sum() # 再次手动拷贝得到累积分布的字典 cumulativeDistributionFunction = {k: v.copy() for k, v in probabilities.items()} for key in cumulativeDistributionFunction: for index, x in enumerate(cumulativeDistributionFunction[key]): if index == 0: continue else: cumulativeDistributionFunction[key][index] += cumulativeDistributionFunction[key][index-1]
这样处理后,bins、probabilities、cumulativeDistributionFunction就是三个完全独立的字典,里面的numpy数组也各自占用独立内存,修改其中一个不会影响另外两个。
内容的提问来源于stack exchange,提问作者Daniel B
相关产品推荐
相关产品推荐

