如何从字典生成器中一起添加多个字典以创建单个整理的python字典

时间:2014-08-26 20:15:38

标签: python dictionary generator dictionary-comprehension

我正在寻求帮助这样做pythonic方式。

到目前为止,我的代码 我创建了一个生成器来创建一个字典,其中一个元组作为一个键,链接到我想在项目中稍后使用的对象。
我相信有更好的方法可以做到这一点。我作为字典和列表理解的尝试没有成功。

app = models.get_app('djangoapp')
appmodels = models.get_models(app)

gen = mapEntGen(appmodels)  
d = {}  
for x in gen:  
    d.update(x)   

让我的对象看起来更清晰。

for x in gen:
    print(x)

{('in', 1): <class 'djangoapp.models.entrance01IN'>}
{('out', 1): <class 'djangoapp.models.entrance01OUT'>}
{('in', 2): <class 'djangoapp.models.entrance02IN'>}
{('out', 2): <class 'djangoapp.models.entrance02OUT'>}
...

这些是我理解失败的尝试

{d: aDict for aDict in mapEntGen(appmodels)}  
d = {key: value for (key, value) in gen}  
d = {key: value for (key, value) in mapEntGen(appmodels[1:])}  

我认为问题很可能是它已经是字典而不是其他两种类型。这可以用作键值对。

----> 1 for k, v in gen:
      2     d[k] = v
      3 

ValueError: need more than 1 value to unpack

这是我用于生成器的其他代码,用于构建对象映射和查找它们的键。

def mapEntGen(EntranceObj = []):    
    for x in EntranceObj:
        thisEnt = (x._meta.verbose_name[10:],
                   int(x._meta.verbose_name[8:10]))
        aDict = {thisEnt : x}
        yield aDict

它可能看似重复但我没有尝试过按照我迄今为止尝试的所有示例工作。

2 个答案:

答案 0 :(得分:1)

回答问题的最简单方法是放弃mapEntGen,并执行以下操作:

d = {((x._meta.verbose_name[10:],
       int(x._meta.verbose_name[8:10])):x 
           for x in EntranceObj}

没有必要创建不同的词典然后将它们组合起来。


如果您热衷于使用生成器 - 为什么它会返回字典,而字典只有一个键和值?让它返回一个元组:

def mapEntGen(EntranceObj = []):    
    for x in EntranceObj:
        thisEnt = (x._meta.verbose_name[10:],
                   int(x._meta.verbose_name[8:10]))
        yield (thisEnt, x)

然后获得d很简单:

d = dict(mapEntGen(appmodels))

如果您想使用 生成器:

mapEntGen(appmodels)生成词典 - 对待它们。当你想要迭代他们的项目时,你必须调用iteritems,然后迭代它们。这应该有效:

d = {key:value for subdct in gen for key, value in subdct.iteritems()}  

为了确保你理解这种理解,这相当于做:

d = {}
for subdct in gen:
    for key, value in subdct.iteritems():
        d[key] = value

(当然gen可以替换为mapEntGen(appmodels)

答案 1 :(得分:1)

只是为了给代码提供一个完全不同的方向,这可能更具可读性和可用性,具体取决于代码的其余部分:

代替mapGenEnt,让我们从appModels创建两个独立的生成器(无论是什么):

  1. 代码列表(您稍后将其用作密钥,例如('out', 1)
  2. 实际对象/模型的列表(您稍后将其用作值,例如<class 'djangoapp.models.entrance01IN'>
  3. 所以,假设你有这两个发生器:

    def code_names(EntranceObj):
       return ((entrance._meta.verbose_name[10:], int(entrance._meta.verbose_name[8:10]) for entrance in EntranceObj)
    
    def entries(EntranceObj):
       return EntranceObj    # Shorter than: (entrance for entrance in EntranceObj)
    

    现在我们有两个明确做自己的事情,我们必须创建d。使用zipitertools.izip

    很容易
    d = dict(zip(code_names(appmodels), entries(appmodels)))
    

    为了提高可读性,我个人会给这个函数命名为generate_model_entries(appmodels)

    def generate_model_entries(models):
        return dict(zip(code_names(models), entries(models)))
    
    d = generate_model_entries(appmodels)
    

    PS:如果您的循环变量的名称比x更准确,请;使用它。