在为我的研究编码时,我必须经常这样做。您将需要使用 defaultdict 包,因为它允许您通过简单的分配在任何级别添加键:值对。回答完你的问题后我会告诉你的。这直接来自我的一个程序。关注最后 4 行(不是注释),并通过块的其余部分追溯变量以查看它在做什么:
from astropy.io import fits #this package handles the image data I work with
import numpy as np
import os
from collections import defaultdict
klist = ['hdr','F','Ferr','flag','lmda','sky','skyerr','tel','telerr','wco','lsf']
dtess = []
for file in os.listdir(os.getcwd()):
if file.startswith("apVisit"):
meff = fits.open(file, mode='readonly', ignore_missing_end=True)
hdr = meff[0].header
oid = str(hdr["OBJID"]) #object ID
mjd = int(hdr["MJD5"].strip(' ')) #5-digit observation date
for k,v in enumerate(klist):
if k==0:
dtess = dtess+[[oid,mjd,v,hdr]]
else:
dtess=dtess+[[oid,mjd,v,meff[k].data]]
#header extension works differently from the rest of the image cube
#it's not relevant to populating dictionaries
#HDUs in order of extension no.: header, flux, flux error, flag mask,
# wavelength, sky flux, error in sky flux, telluric flux, telluric flux errors,
# wavelength solution coefficients, & line-spread function
dtree = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))
for s,t,u,v in dtess:
dtree[s][t][u].append(v)
#once you've added all the keys you want to your dictionary,
#set default_factory attribute to None
dtree.default_factory = None
这是摘要版本。
- 首先,对于 n 级字典,您必须以 [key_1, key_2, ... , key_n, value] 的形式将所有内容排序并转储到 (n+1) 元组列表中。
- 然后,要初始化 n 级字典,只需键入“defaultdict(lambda:”(减去引号) n-1 次,最后粘贴“defaultdict(list)”(或其他数据类型),然后关闭括弧。
- 使用 for 循环附加到列表中。*注意:当您访问最低级别的数据值时,您可能必须键入 my_dict[key_1][key_2] [...][key_n][0] 来获取实际值,而不仅仅是数据的描述在其中键入。
- *编辑:当你的字典和你想要的一样大时,将 default_factory 属性设置为 None。
如果您尚未将 default_factory 设置为 None,您可以稍后通过键入类似 my_dict[key_1][key_2][...][new_key]=new_value 或使用 append() 命令来添加到嵌套字典。您甚至可以添加其他词典,只要您通过这些分配形式添加的词典本身没有嵌套。
*
警告!该代码片段新添加的最后一行,将 default_factory 属性设置为 None,非常重要。您的 PC 需要知道您何时完成向字典的添加,否则它可能会继续在后台分配内存以防止缓冲区溢出,从而耗尽您的 RAM,直到程序停止运行。这是一种内存泄漏。写完这个答案后,我很难学到这一点。这个问题困扰了我好几个月,我什至不认为我是最终解决这个问题的人,因为我对内存分配一无所知。