【问题标题】:Nested dictionary comprehension: Too many values to unpack嵌套字典理解:解包的值太多
【发布时间】:2017-12-05 11:05:35
【问题描述】:

我尝试重写以下代码以使用字典理解,只是为了好玩:

import itertools

with open('foo.txt') as f:
    entities = f.read().splitlines()

parsed_entities = []
while entities:
    props = itertools.takewhile(lambda n: n != 'EOM', entities)
    entity = {p.split('=')[0]: p.split('=')[1] for p in props}
    entities = entities[len(entity)+2:]  # Delete and skip EOM & newline
    parsed_entities.append(entity)

我想替换这一行:

entity = {p.split('=')[0]: p.split('=')[1] for p in props}

具有更好看的字典理解,可能如下所示:

entity = {key: value for p in props for key, value in p.split('=')}

当我尝试这样做时,我收到以下错误:

ValueError:解包的值太多(预计 2 个)

我做错了什么?使用ipdb.pm()我看到p是name=yam,这很好,但是keyvalue是未定义的。

【问题讨论】:

  • 我认为p.split('=')的长度不是2。
  • @SamChats:确实如此。但p.split('=')[0] 不是,这就是正在解包的内容。
  • @SamChats,检查一下。我用print(len(p.split('=')))替换了p.split('='),是2。
  • @MartijnPieters 明白了。很有见地:)

标签: python python-3.x dictionary dictionary-comprehension


【解决方案1】:

你不能这样做:

for key, value in p.split('=')

因为这要求p.split() 调用的每个结果都恰好有两个 元素。相反,您只有一系列可变长度的单个(字符串)元素。

您必须先将 p.split() 包装到另一个可迭代对象中:

entity = {key: value for p in props for key, value in (p.split('='),)}

所以现在代替:

['key', 'value']

你得到:

(['key', 'value'],)

只迭代一次,提供两个值来解包。

但是,您可以在此处使用 dict() 可调用对象;它直接使用 (key, value) 对的可迭代对象:

entity = dict(p.split('=') for p in props)

您还应该尽量避免将整个文件读入内存,您可以将文件用作可迭代的直接

from itertools import takewhile

parsed_entities = []
with open('foo.txt') as f:
    cleaned = (l.rstrip('\n') for l in f)
    while True:
        props = takewhile(lambda n: n != 'EOM', cleaned)
        parsed_entities.append(dict(p.split('=') for p in props))
        try:
            next(cleaned)  # consume line after EOM
        except StopIteration:
            # no more lines
            break

【讨论】:

  • 您的解决方案绝对有效,谢谢!但我想试着理解。打印p.split('=') 结果为['a', 'b']。为什么说是变长序列?
  • @Infinity: 'a' 是长度为 1 的字符串,但您可以使用 'foo''bar' 或更长或更短的字符串。 for 循环遍历这两个字符串,而不是它们对,所以对于['a', 'b'],您首先尝试执行key, value = 'a'。这是行不通的,因为长度为 one 的字符串中只有一个字符。但是key, value = 'ac' 可以,这是一个长度为 2 的字符串。
  • 终于搞定了。谢谢:)
猜你喜欢
  • 1970-01-01
  • 2017-11-27
  • 2021-07-24
  • 2013-07-28
  • 2011-06-06
  • 2017-11-10
  • 2016-12-25
  • 2021-09-19
相关资源
最近更新 更多