# [Tutor] write dictionary to file

Steven D'Aprano steve at pearwood.info
Mon Jun 23 16:54:30 CEST 2014

```On Mon, Jun 23, 2014 at 09:17:44AM +0000, Ian D wrote:

> > for row in spamreader:
> >     if row['year'] == '40':
> >         email = row['user'] + '@email.com'
> >         output = [ row[fieldname] for fieldname in fields ]
>
> I am unsure about this syntax [ row[fieldname] for fieldname in fields ]

That's called a "list comprehension". It is a way of building up a list
as a single expression. Let's start with the old-fashioned way to build
a list:

output = []
for fieldname in fields:
output.append( row[fieldname] )

Or, we can do exactly the same thing, in a single line, with a list
comprehension, and get rid of the temporary variables:

output = [row[fieldname] for fieldname in fields]

If you remember your high school maths classes, the form of the list
comp is rather close to that of mathematical set builder notation:

http://www.mathsisfun.com/sets/set-builder-notation.html

Here is a set builder notation, and its English translation:

{2n+1 : n ∈ {1,2,3,4}}

This reads as "the set of 2n plus 1, such that n is an element of
{1,2,3,4}". Don't be confused by the fact that there is a set inside a
set -- this just tells us how to build a new set from an old set.

So we start with a set {1,2,3,4}, and let n equal each of those numbers
in turn. Then we calculate 2n+1, and use that inside the new set we're
creating:

n = 1, so 2n+1 => 3
n = 2, so 2n+1 => 5
n = 3, so 2n+1 => 7
n = 4, so 2n+1 => 9

and so the final result is the set {3, 5, 7, 9}.

Enough about sets and mathematics! Now we're going to talk about Python!
Python uses the same sort of expression, except it builds a list, not a
set, and calls it a "list comprehension" instead of a "list builder".
(Don't blame me for that, blame the Haskell programming language which
invented this.)

So, we start with the mathematical set builder:

{2n+1 : n ∈ {1,2,3,4}}

Turn the sets into lists:

[2n+1 : n ∈ [1,2,3,4]]

Use Python syntax for the formula:

[2*n+1 : n ∈ [1,2,3,4]]

Replace the "such that" and "element of" with "for" "in":

[2*n+1 for n in [1,2,3,4]]

and now you have a Python list comprehension. If you copy and paste that
into a Python interpreter, you'll see this:

py> [2*n+1 for n in [1,2,3,4]]
[3, 5, 7, 9]

> > # DictWriter needs a dict, not a list.
> > spamwriter.writerow({name: row[name] for name in fields})
>
> And this writerow syntax is something new for me, as are dictionaries
> (which I have tried to read up and understand.)

List comprehensions were added to Python in, I think, version 2.2, which
was about ten years ago. They turned out to be so useful and popular
that now, in Python 3, we have FOUR different kinds of "comprehensions"
or builder syntax:

List comprehensions:
[2*n+1 for n in [1,2,3,4]]

Generator expressions (like a list comp, except values are created
lazily on demand, rather than all at once):
(x+1 for x in [2, 4, 6, 8])

Set comprehensions (like a list comp, except it builds a set rather than
a list):
{char.lower() for char in "Hello World!"}

Dict comprehensions (like a list comp, except it builds a dictionary of
key:value pairs):
{char: char.lower() for char in "Hello World!"}

So what is a dict? A dict, short for dictionary, is a table of keys with
associated values. Think of them as being like words and definitions:

words = {
"cat": "a small mammal that purrs",
"dog": "man's best friend",
"snake": "a lizard with no legs",
"ostrich": "biggest bird in the world"
}

The first part, before the colon, is the key. The part after the colon
is the value associated with that key. If you want to know the meaning
of a word, you look it up in the dictionary:

py> print(words['dog'])
man's best friend

To add a new word:

py> words['kangeroo'] = 'jumping marsupial from Australia'
py> print(words['kangeroo'])
jumping marsupial from Australia

So I've already shown you the dict comprehension form:

spamwriter.writerow({name: row[name] for name in fields})

Here is how we can do it the old-fashioned way without a dict comp:

table = {}
for name in fields:
value = row[name]
table[name] = value

spamwriter.writerow(table)

Does this help? Ask any further questions you may have.

--
Steven
```