Reputation: 6581
I try to rewrite the following code to work with dictionary comprehension, just for fun:
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)
I want to replace this line:
entity = {p.split('=')[0]: p.split('=')[1] for p in props}
With a better looking dictionary comprehension, which might look like:
entity = {key: value for p in props for key, value in p.split('=')}
When I try to do so, I get the following error:
ValueError: too many values to unpack (expected 2)
What am I doing wrong? Using ipdb.pm()
I saw that p is name=yam
, which is good, but key
and value
are undefined.
Upvotes: 2
Views: 1382
Reputation: 1122312
You can't do this:
for key, value in p.split('=')
because that requires every result of the p.split()
call to have exactly two elements. Instead, you just have a sequence of single (string) elements, of variable length.
You'd have to wrap p.split()
into another iterable first:
entity = {key: value for p in props for key, value in (p.split('='),)}
So now instead of:
['key', 'value']
You get:
(['key', 'value'],)
which iterates just once, providing two values to unpack.
However, you could just use the dict()
callable here; it consumes an iterable of (key, value)
pairs directly:
entity = dict(p.split('=') for p in props)
You should also try to avoid reading the whole file into memory, you can use the file as an iterable directly:
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
Upvotes: 6