【问题标题】:How to construct nested dictionary comprehension in Python with correct ordering?如何在 Python 中以正确的顺序构造嵌套字典理解?
【发布时间】:2013-12-25 03:21:30
【问题描述】:

当我遇到问题时,我试图缩短 this problem 的代码。

基本上,我正在尝试嵌套字典理解,但尝试失败。 这是我尝试过的。

dict2 = {key:value for key, value in line.split(":")
                   for line in ["1:One", "2:Two", "4:Four"]}
print dict2

当我运行它时,它给了我

NameError: name 'line' is not defined

而且,当我像这样反转for 语句时

dict2 = {key:value for line in ["1:One", "2:Two", "4:Four"]
                   for key, value in line.split(":")}
print dict2

结果

ValueError: need more than 1 value to unpack

我需要有关dictionary(或list)理解嵌套结构的帮助。举个例子会有很大帮助。

【问题讨论】:

  • 这实际上是一个极好的问题,并强调了 Python 文档中完全未解决的问题。也有很多方法可以很好地实现这一点。希望这会被记录下来,这样我们就不会变成 PERL...
  • @smci Python 是开源的,您可以随时提交补丁 :) 文档比代码更容易,因为需要最少的测试。

标签: python dictionary nested dictionary-comprehension


【解决方案1】:

请注意,在没有 dict 理解的情况下,有更好的方法可以做到这一点;见下文。我将首先解决您的方法的问题。

您需要在推导中使用嵌套顺序。按照嵌套常规循环时的顺序列出循环。

line.split() 表达式返回一个包含两个项目的序列,但每个项目都不是键和值的元组;相反,只有 one 元素被迭代。将拆分包装在一个元组中,这样您就可以生成 (key, value) 项目的“序列”,以将两个结果分配给两个项目:

dict2 = {key:value for line in ["1:One", "2:Two", "4:Four"]
                   for key, value in (line.split(":"),)}

这相当于:

dict2 = {}
for line in ["1:One", "2:Two", "4:Four"]:
    for key, value in (line.split(":"),):
        dict2[key] = value

只需要嵌套循环,因为你不能这样做:

dict2 = {}
for line in ["1:One", "2:Two", "4:Four"]:
    key, value = line.split(":")
    dict2[key] = value

但是,在这种情况下,您应该使用 dict() 构造函数,而不是字典解析。它想要两个元素的序列,简化整个操作:

dict2 = dict(line.split(":") for line in ["1:One", "2:Two", "4:Four"])

【讨论】:

  • 我更喜欢使用dict(el.split(':') for el in the_list)
  • 那么,只有tuple 允许我们为多个变量赋值(通过解包)?!
  • @AshishNitinPatil:你在这里有for key, value in ('key', 'value'),这是行不通的。但是for key, value in (('key', 'value'),) 确实
  • @AshishNitinPatil:for 循环正在将元组解包成两个变量,因此每次迭代右侧的序列必须 包含两个元素。 line.split(':') 创建一个只有 一个 元素的序列。
  • @AshishNitinPatil:只有当它返回一个 sequence 的 2 值对时。当然,它也可以是一个迭代器,但每次迭代都必须产生一对值。
【解决方案2】:

您可以使用dictgenerator expression 更简单地做到这一点:

>>> lst = ["1:One", "2:Two", "4:Four"]
>>> dict(x.split(":") for x in lst)
{'4': 'Four', '1': 'One', '2': 'Two'}
>>>

【讨论】:

  • 这实际上比公认的答案(元组拆包/重新包装奥运会)要优雅得多,应该是公认的答案。抄送@MartijnPieters
  • @smci 但这不是问题所要求的。 Martijn 的回答很好地描述了我做错了什么,应该如何完成以及如何在没有听写理解的情况下有效地做到这一点。
  • @AshishNitinPatil:是的,我独立来到这里寻找相同的内容(嵌套字典理解中的订单/解包问题)。但是将nested-dict-comp 方法与使用 dict-constructor-taking-tuples-of-(key,value) 进行比较,我们清楚地看到 (key,value)-pair-tuple-inside-a-1-tuple解决拆包/订购的方法是一种 Python 反模式,它是如此糟糕和令人困惑,以至于应该警告用户不要使用它,非常响亮和清晰。就像我说的,如果我们允许 33 种实现方式,其中 32 种是次优且不可读的,我们很快就会变成 PERL。哪些是要避免的
猜你喜欢
  • 1970-01-01
  • 2013-07-28
  • 2011-06-06
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 2016-11-25
  • 2018-06-14
相关资源
最近更新 更多