嵌套字典理解:要解压缩的值太多

Inf*_*ity 2 python dictionary python-3.x dictionary-comprehension

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

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)
Run Code Online (Sandbox Code Playgroud)

我想替换这一行:

entity = {p.split('=')[0]: p.split('=')[1] for p in props}
Run Code Online (Sandbox Code Playgroud)

具有更好看的字典理解,可能看起来像:

entity = {key: value for p in props for key, value in p.split('=')}
Run Code Online (Sandbox Code Playgroud)

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

ValueError:解压缩的值太多(预期2)

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

Mar*_*ers 6

你不能这样做:

for key, value in p.split('=')
Run Code Online (Sandbox Code Playgroud)

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

你必须首先包装p.split()到另一个迭代:

entity = {key: value for p in props for key, value in (p.split('='),)}
Run Code Online (Sandbox Code Playgroud)

所以现在而不是:

['key', 'value']
Run Code Online (Sandbox Code Playgroud)

你得到:

(['key', 'value'],)
Run Code Online (Sandbox Code Playgroud)

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

但是,你可以在dict()这里使用callable; 它(key, value)直接消耗一对迭代:

entity = dict(p.split('=') for p in props)
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)