在Python中初始化/创建/填充Dict的Dict
我以前在python中使用过词典,但我对python还是新手。这一次我用的是一本字典的一本字典的一本字典的一本字典。。。i、 例如,一个三层dict,并希望在编程之前进行检查 我想将所有数据存储在这个三层dict中,我想知道什么是一种很好的Python方式来初始化,然后读取文件并写入这样的数据结构 我想要的词典类型如下:在Python中初始化/创建/填充Dict的Dict,python,dictionary,Python,Dictionary,我以前在python中使用过词典,但我对python还是新手。这一次我用的是一本字典的一本字典的一本字典的一本字典。。。i、 例如,一个三层dict,并希望在编程之前进行检查 我想将所有数据存储在这个三层dict中,我想知道什么是一种很好的Python方式来初始化,然后读取文件并写入这样的数据结构 我想要的词典类型如下: {'geneid': {'transcript_id': {col_name1:col_value1, col_name2:col_value2} } } 数据属于以下类型:
{'geneid':
{'transcript_id':
{col_name1:col_value1, col_name2:col_value2}
}
}
数据属于以下类型:
geneid\ttx_id\tcolname1\tcolname2\n
hello\tNR432\t4.5\t6.7
bye\tNR439\t4.5\t6.7
有没有什么好办法
谢谢 首先,让我们从处理行解析的模块开始:
import csv
with open('mydata.txt', 'rb') as f:
for row in csv.DictReader(f, delimiter='\t'):
print row
这将打印:
{'geneid': 'hello', 'tx_id': 'NR432', 'col_name1': '4.5', 'col_name2': 6.7}
{'geneid': 'bye', 'tx_id': 'NR439', 'col_name1': '4.5', 'col_name2': 6.7}
所以,现在你只需要把它重新组织成你喜欢的结构。这几乎是微不足道的,只是您必须处理这样一个事实:第一次看到给定的geneid
时,您必须为它创建一个新的空dict
,同样,第一次在geneid
中看到给定的tx\u id
。您可以通过以下方法解决此问题:
您可以使用以下工具使其更具可读性:
这里的诀窍是,顶级的
dict
是一个特殊的函数,每当它第一次看到一个新键时,就会返回一个空的dict
,而它返回的空dict
本身就是一个空的dict
。唯一困难的部分是defaultdict
采用返回正确类型对象的函数,而返回defaultdict(dict)
的函数必须使用partial
、lambda
或显式函数编写。(ActiveState上有一些配方,PyPI上有一些模块,它们将为您提供一个更通用的版本,如果您愿意的话,可以根据需要创建新的词典。)我也在尝试寻找替代方案,并在stackoverflow中找到了这个同样不错的答案:
就我而言,基本上:
class AutoVivification(dict):
"""Implementation of perl's autovivification feature."""
def __getitem__(self, item):
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
在为我的研究编写代码时,我必须经常这样做。您需要使用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
这是摘要版
警告!新添加的代码段的最后一行非常重要,您可以将默认的\u factory属性设置为None。您的电脑需要知道您何时完成了向字典的添加,否则它可能会继续在后台分配内存,以防耗尽RAM,直到程序停止。这是非常重要的一种。在我写下这个答案后不久,我通过艰苦的方式学会了这一点。这个问题困扰了我好几个月,我甚至不认为我是最终解决这个问题的人,因为我对内存分配一无所知。你是说“高效”吗就您的时间编码和维护而言,或者就执行它的CPU时间而言?对不起,好的一点,编码和维护…对于更多的列,您可以对col_name中的col_name执行
:genes[row['geneid'].[row['transcript_id'].[col_name]=row[col_name]
不使用functools.partial
和执行genes=defaultdict(lambda:defaultdict(dict))是否有缺点?@StevenRumbalski:partial
和lambda
之间没有太大区别。我个人觉得前者更容易理解,因为我知道它只不过是在函数中绑定参数,而lambda
可以做任何事情。但这是一个风格问题。我使用lambda
when表达式才是最重要的;partial
当中心函数是最重要的;def
当它们都不够明显时。是的,当我说,“ActiveState上有一些配方,PyPI上有一些模块,它们将为您提供一个更通用的版本,如果您愿意的话,可以根据需要创建新的词典。”这就是我的意思。有几种不同的方法可以做到这一点(有些甚至像perl和JS一样,根据索引的类型神奇地创建字典或列表)。
class AutoVivification(dict):
"""Implementation of perl's autovivification feature."""
def __getitem__(self, item):
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
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