首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Python中初始化/创建/填充字典的字典

在Python中初始化/创建/填充字典的字典
EN

Stack Overflow用户
提问于 2013-03-01 07:32:57
回答 3查看 398关注 0票数 4

我以前在python中使用过字典,但我仍然是python的新手。这次我用的是字典的字典,字典的字典……即三层字典,并且想要在对其进行编程之前进行检查。

我想在这个三层字典中存储所有数据,并且想知道什么是一种很好的pythonic初始化方式,然后读取文件并写入这样的数据结构。

我想要的字典类型如下:

代码语言:javascript
复制
{'geneid':
{'transcript_id':
{col_name1:col_value1, col_name2:col_value2}
}
}

数据类型如下:

代码语言:javascript
复制
geneid\ttx_id\tcolname1\tcolname2\n
hello\tNR432\t4.5\t6.7
bye\tNR439\t4.5\t6.7

你有什么好办法吗?

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-03-01 07:46:19

首先,让我们从csv模块开始处理行的解析:

代码语言:javascript
复制
import csv
with open('mydata.txt', 'rb') as f:
    for row in csv.DictReader(f, delimiter='\t'):
        print row

这将打印以下内容:

代码语言:javascript
复制
{'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_id时,也必须为它创建一个新的空and。你可以用setdefault来解决这个问题

代码语言:javascript
复制
import csv
genes = {}
with open('mydata.txt', 'rb') as f:
    for row in csv.DictReader(f, delimiter='\t'):
        gene = genes.setdefault(row['geneid'], {})
        transcript = gene.setdefault(row['tx_id'], {})
        transcript['colname1'] = row['colname1']
        transcript['colname2'] = row['colname2']

您可以使用defaultdict使其更具可读性

代码语言:javascript
复制
import csv
from collections import defaultdict
from functools import partial
genes = defaultdict(partial(defaultdict, dict))
with open('mydata.txt', 'rb') as f:
    for row in csv.DictReader(f, delimiter='\t'):
        genes[row['geneid']][row['tx_id']]['colname1'] = row['colname1']
        genes[row['geneid']][row['tx_id']]['colname2'] = row['colname2']

这里的诀窍在于,顶级dict是一个特殊的…,每当它第一次看到新的密钥…时,它都会返回一个空的dict并且它返回的空dict本身就是一个空dict。唯一困难的部分是,defaultdict接受返回正确类型对象的函数,而返回defaultdict(dict)的函数必须使用partiallambda或显式函数编写。( ActiveState上的食谱和PyPI上的模块将为您提供一个更通用的版本,如果您愿意,它可以根据需要创建新的字典。)

票数 4
EN

Stack Overflow用户

发布于 2013-03-01 07:55:58

我也在努力寻找替代方案,并在stackoverflow中得出了这个也很好的答案:

What's the best way to initialize a dict of dicts in Python?

基本上在我的例子中:

代码语言:javascript
复制
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
票数 2
EN

Stack Overflow用户

发布于 2014-09-18 10:42:57

我必须在为我的研究编写代码时例行公事地这样做。您将希望使用defaultdict包,因为它允许您通过简单的赋值在任何级别添加key:value对。回答完你的问题后,我会给你看的。这是直接来自我的一个程序。关注最后4行(不是注释),在代码块的其余部分跟踪变量,看看它在做什么:

代码语言:javascript
复制
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

以下是摘要版本。

  1. 首先,对于n级字典,您必须将所有内容排序并转储到(n+1)值的列表中,格式为key_1,key_2,...,key_n,-tuples。然后,要初始化n级字典,只需键入“

(lambda:”(减去引号) n-1次,在末尾粘贴“defaultdict(

  1. )”(或其他一些数据类型),然后关闭括号。
  2. 使用for循环追加到列表中。*注意:当您访问最低级别的数据值时,您可能必须键入my_dictkey_1 ...当您的字典和您想要的一样大时,要获得实际值,而不仅仅是数据类型therein.
  3. *Edit:的描述,请将default_factory属性设置为None。

如果没有将default_factory设置为None,则可以稍后通过键入my_dictkey_1...=new_value之类的内容或使用append()命令添加到嵌套字典中。您甚至可以添加额外的字典,只要您通过这些赋值形式添加的字典本身不是嵌套的。

*警告!将default_factory属性设置为None的代码片段中新添加的最后一行非常重要。你的电脑需要知道你什么时候添加完你的字典,否则它可能会继续在后台分配内存以防止buffer overflow,直到程序停止为止。这是memory leak的一种类型。在我写了这个答案之后,我以一段艰难的方式学会了这一点。这个问题困扰了我几个月,我甚至不认为我是最后解决这个问题的人,因为我对内存分配一无所知。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15147740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档