Hi, my name is Jesse and I abuse list comprehensions.

I just found myself being quite abusive.

I have a series of dict{key:[list]) style objects, and I wanted to unpack it, convert it to a string, etc. (yes, variable names have been changed to protect the innocent)

?View Code PYTHON
1
return ',',join(['{{whizbang|%s}}' % i['foo'] for i in [ i for i in myDict[keyname]]])

Now, this could only be better if I:

  • Included a lambda
  • Had another nested comprehension

Other than the fact that what I wrote above is next to untestable – it’s also hard to understand unless well, you’re me. In order to debug it, you’d have to pprint the inbound dict and slowly unravel (from left to right) the operations being done.

Luckily, there’s no math there!

So, I “cleaned” it up:

?View Code PYTHON
1
2
3
4
whizlist = []
for item in [k for k in myDict[keyname]]:
    whizlist.append('{{whizbang|%s}}' % item['foo'])
return ','.join(whizlist)

Hmm, I still seem to be juggling chainsaws here. Let’s go for the “easy” button:

?View Code PYTHON
1
2
3
4
whizlist = []
for item in myDict[keyname]:
	whizlist.append('{{whizbang |%s}}' % item['foo'])
return ','.join(whizlist)

I could argue that the first is “faster” (although I’d need to prove it) – but ultimately the final “un-optimized” version is more pythonic.

  • I could argue that the first has a typo, although you'd need to execute it.
  • I find list comprehensions easier to grok when they are written on multiple lines.

    [ value
    for item in sequence
    (if condition)
    ]
  • Martin
    The following expressions are equivalent, which one would you choose? ;-)

    mylist
    [x for x in mylist]
    [y for y in [x for x in mylist]]
    [z for z in [y for y in [x for x in mylist]]]
    [q for q in [z for z in [y for y in [x for x in mylist]]]]

    ok... you get the point. (Strictly speaking they are not complely equivalent since the first of them doesn't yield a copy of the list but is rather a reference to the original)
  • [q for q in [z for z in [y for y in [x for x in mylist]]]]

    mmmm. Delicious. Jam a lambda and a couple of .method() calls on the objects being iterated through and it will be complete.
  • What about:

    whizzes = (d['foo'] for d in myDict[keyname])
    return ','.join('{{whizbang |%s}}' % whiz for whiz in whizzes)
  • Hmm, good question. I'll have to try that one out, although I still have to go with option 3
  • Nes
    I might be missing something by why didn't you just do:

    return ',',join( '{{whizbang|%s}}' % i['foo'] for i in myDict[keyname] )

    ?
  • or

    return ',',join( '{{whizbang|%(foo)s}}' % i for i in myDict[keyname] )
  • mike
    not to mention return ','.join(['{{whizbang|%s}}' % v for v in myDict[keyname].values()])
  • Still not convoluted enough
blog comments powered by Disqus