20090203

Updating a list of dictionaries with the same key-value pair

One colleague of mine recently asked how can you add a certain key-value pair to all dictionaries contained in a list.

The obvious (and long) solution would be the simple iterative way:

>>> l = [ {'a' : 1, 'b' : 2}, {'a' : 3, 'f' : 4} ]
>>> for i in l:
... i['c'] = 6
...
>>> print l
[{'a': 1, 'c': 6, 'b': 2}, {'a': 3, 'c': 6, 'f': 4}]

This works, but it's not very nice. When you start to get comfortable with Python after an OOP and/or procedural language, you realise that there's a whole new world hidden in the functional way of doing things. Your first attempt at solving this problem with list comprehension might look like this:

>>> l = [ {'a' : 1, 'b' : 2}, {'a' : 3, 'f' : 4} ]
>>> [i['c'] = 6 for i in l]
File "", line 1
[i['c'] = 6 for i in l]
^
SyntaxError: invalid syntax

Sadly, assignments don't work in this instance. However, dictionaries have the convenient update method, that does just this:

>>> l = [ {'a' : 1, 'b' : 2}, {'a' : 3, 'f' : 4} ]
>>> [i.update ({'c' : 6}) for i in l]
[None, None]
>>> print l
[{'a': 1, 'c': 6, 'b': 2}, {'a': 3, 'c': 6, 'f': 4}]

The syntax might look a bit hairy at first, because update takes a dictionary and merges it's values to the one that the method is called upon, keeping the values that are missing from the new dictionary.

Happy coding!

20090119

Sorting a dictionary by value

In Python you sometimes need to sort a dictionary based on its values, not the keys, as the built-in sorted function does:


>>> a = { 'a' : 1, 'b' : 3, 'd' : 2, 'c' : 4 }

>>> sorted (a)

['a', 'b', 'c', 'd']


Not exactly the output we wished for. This is because dictionary iterators iterate over the keys and not the values.


There are several possible solutions to this problem, the simplest is to add specific key parameter to sorted:


>>> sorted (a, key=(lambda x: a[x]))

['a', 'd', 'b', 'c']


This way you can iterate over the dictionary in the order of preference:


>>> for i in sorted (a, key=(lambda x: a[x])):

... print a[i]

...

1

2

3

4


Note that if you try to construct a dictionary from the sorted list it will not yield a sorted dictionary:


>>> dict ([(x, a[x]) for x in sorted (a, key=(lambda z: a[z]))])

{'a': 1, 'c': 4, 'b': 3, 'd': 2}


Dictionaries uses hashes, so the order is not guaranteed. This is why you have to construct a temporary list with the sorted keys to iterate over the dictionary in the desired order (in this case sorted by the value). In real world scenarios you sometimes have a dictionary of dictionaries, and this way you can choose the parameter you iterate over.


20090116

Ternary operator in Python

People coming from C-style languages such as PHP and C++ often wonder why there is no ternary operator (the weird x ? y : z construct) in Python.


This operator is usually used in assigments, for example


someval = (condition() ? value1 : value2);


Where someval's value depends on the return value of the function named condition(). If condition returns a value that evaluates to true, then someval will be set to value1, if false then value2.


The fact is that there is a way in Python that lets you use this kind of assignments. The trick is to use the conditional operators.


Here's an example:


>>> condition = True
>>> x = condition and 'is true' or 'is false'
>>> print 'condition %s' % x
condition is true
>>> condition = False
>>> x = condition and 'is true' or 'is false'
>>> print 'condition %s' % x
condition is false


The rule that enables this is that the return value of a logical operation (if true) is always the last value. This guarantees that x will always get a value.


Of course in C-style languages there are things one can do with the ternary operator that would fail in Python, but with logical operators the most typical use of it can be simulated, and it's even a bit more readable for people who are not very familiar with the language. I would even go as far as saying it's syntax is superior to the ? : notation.