1.13. Mapping lists

One of the most powerful features of Python is the list comprehension, which provides a compact way of mapping a list into another list by applying a function to each of the elements of the list.

Example 1.31. Introducing list comprehensions

>>> li = [1, 9, 8, 4]
>>> [elem*2 for elem in li]      1
[2, 18, 16, 8]
>>> li                           2
[1, 9, 8, 4]
>>> li = [elem*2 for elem in li] 3
>>> li
[2, 18, 16, 8]
1 To make sense of this, look at it from right to left. li is the list you’re mapping. Python loops through li one element at a time, temporarily assigning the value of each element to the variable elem. Python then applies the function elem*2 and appends that result to the returned list.
2 Note that list comprehensions do not change the original list.
3 It is safe to assign the result of a list comprehension to the variable that you’re mapping. There are no racing conditions or any weirdness to worry about; Python constructs the new list in memory, and when the list comprehension is complete, it assigns the result to the variable.

Example 1.32. List comprehensions in buildConnectionString

["%s=%s" % (k, v) for k, v in params.items()]

First, notice that you’re calling the items function of the params dictionary. This function returns a list of tuples of all the data in the dictionary.

Example 1.33. keys, values, and items

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.keys()   1
['server', 'uid', 'database', 'pwd']
>>> params.values() 2
['mpilgrim', 'sa', 'master', 'secret']
>>> params.items()  3
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
1 The keys method of a dictionary returns a list of all the keys. The list is not in the order in which the dictionary was defined (remember, elements in a dictionary are unordered), but it is a list.
2 The values method returns a list of all the values. The list is in the same order as the list returned by keys, so params.values()[n] == params[params.keys()[n]] for all values of n.
3 The items method returns a list of tuples of the form (key, value). The list contains all the data in the dictionary.

Now let’s see what buildConnectionString does. It takes a list, params.items(), and maps it to a new list by applying string formatting to each element. The new list will have the same number of elements as params.items(), but each element in the new list will be a string that contains both a key and its associated value from the params dictionary.

Example 1.34. List comprehensions in buildConnectionString, step by step

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.items()
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
>>> [k for k, v in params.items()]                1
['server', 'uid', 'database', 'pwd']
>>> [v for k, v in params.items()]                2
['mpilgrim', 'sa', 'master', 'secret']
>>> ["%s=%s" % (k, v) for k, v in params.items()] 3
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
1 Note that we’re using two variables to iterate through the params.items() list. This is another use of multi-variable assignment. The first element of params.items() is ('server', 'mpilgrim'), so in the first iteration of the list comprehension, k will get 'server' and v will get 'mpilgrim'. In this case we’re ignoring the value of v and only including the value of k in the returned list, so this list comprehension ends up being equivalent to params.keys(). (You wouldn’t really use a list comprehension like this in real code; this is an overly simplistic example so you can get your head around what’s going on here.)
2 Here we’re doing the same thing, but ignoring the value of k, so this list comprehension ends up being equivalent to params.values().
3 Combining the previous two examples with some simple string formatting, we get a list of strings that include both the key and value of each element of the dictionary. This looks suspiciously like the output of the program; all that remains is to join the elements in this list into a single string.

Further reading