38

I'm playing with some loops in python. I am quite familiar with using the "for" loop:

for x in y:
    do something

You can also create a simple list using a loop:

i = []
for x in y:
   i.append(x)

and then I recently discovered a nice efficient type of loop, here on Stack, to build a list (is there a name for this type of loop? I'd really like to know so I can search on it a little better):

[x.name for x in y]

Ok, that being said, I wanted to go further with the last type of loop and I tried to build a python dictionary using the same type of logic:

{x[row.SITE_NAME] = row.LOOKUP_TABLE for row in cursor}

instead of using:

x = {}
for row in cursor:
   x[row.SITE_NAME] = row.LOOKUP_TABLE

I get an error message on the equal sign telling me it's an invalid syntax. I believe in this case, it's basically telling me that equal sign is a conditional clause (==), not a declaration of a variable.

My second question is, can I build a python dictionary using this type of loop or am I way off base? If so, how would I structure it?

Mike
  • 4,099
  • 17
  • 61
  • 83
  • 4
    The name you are looking for is [`list-comprehension`](http://docs.python.org/2/tutorial/datastructures.html#list-comprehensions) – smac89 Oct 01 '13 at 16:52
  • 1
    You're getting a syntax error because you open it with a square bracket and close it with a curly bracket and because you should use a `:` instead of an `=`: `{x[row.SITE_NAME] : row.LOOKUP_TABLE for row in cursor}` – bheklilr Oct 01 '13 at 16:52
  • 1
    I have made [a video that covers list comprehensions](https://www.youtube.com/watch?v=pShL9DCSIUw) and it's various cousins (set and dict comprehensions, alongside generator expressions), as it comes up so much on SO. Describing it as a 'type of loop' might be underselling it a little. – Gareth Latty Oct 01 '13 at 16:53
  • 1
    comprehensions are great....keep working at it – Tom Swifty Oct 01 '13 at 16:54
  • Thanks everyone! You all answered my question very quickly and I have exactly what I am looking for! Also, I updated the title of the post for future searches. – Mike Oct 01 '13 at 17:00

3 Answers3

60

The short form is as follows (called dict comprehension, as analogy to the list comprehension, set comprehension etc.):

x = { row.SITE_NAME : row.LOOKUP_TABLE for row in cursor }

so in general given some _container with some kind of elements and a function _value which for a given element returns the value that you want to add to this key in the dictionary:

{ _key : _value(_key) for _key in _container }
lejlot
  • 64,777
  • 8
  • 131
  • 164
  • 3
    This is fantastic. I had a feeling this was quite the redundant question on stack, but I couldn't find the name of the loop, so my searches weren't finding the answers I was looking for. This works beautifully. I also threw in a conditional at the end (x = { row.SITE_NAME : row.LOOKUP_TABLE for row in cursor if row.LOOKUP_TABLE <> None} Much much appreciated lejlot and all the others! – Mike Oct 01 '13 at 16:59
9

What you're using is called a list comprehension. They're pretty awesome ;)

They have a cousin called a generator expression that works like a list comprehension but instead of building the list all at once, they generate one item at a time. Hence the name generator. You can even build functions that are generators - there are plenty of questions and sites to cover that info, though.

You can do one of two things:

x = dict(((row.SITE_NAME, row.LOOKUP_TABLE) for row in cursor))

Or, if you have a sufficiently new version of Python, there is something called a dictionary comprehension - which works like a list comprehension, but produces a dictionary instead.

x = {row.SITE_NAME : row.LOOKUP_TABLE for row in cursor}
Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
  • 2
    To clarify, "a sufficiently new version of Python" means 2.7+ For those using <2.7, the first option seems to be the only one available. – hamx0r May 06 '15 at 17:16
6

You can do it like this:

x = dict((row.SITE_NAME, row.LOOKUP_TABLE) for row in cursor)
Carsten
  • 17,991
  • 4
  • 48
  • 53