dict comprehension question.

Terry Reedy tjreedy at udel.edu
Sat Dec 29 18:56:57 EST 2012


On 12/29/2012 2:48 PM, Quint Rankid wrote:

> Given a list like:
> w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
> I would like to be able to do the following as a dict comprehension.
> a = {}
> for x in w:
>      a[x] = a.get(x,0) + 1
> results in a having the value:
> {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1}

Let me paraphrase this: "I have nice, clear, straightforward, 
*comprehensible* code that I want to turn into an incomprehensible mess 
with a 'comprehension." That is the ironic allure of comprehensions.

Comprehensions do not allow for interactions between the source items. 
Mitya and Joel worked around this with solutions that do redundant 
calculation and multiply the time order.

Reductions do allow for interactions. Doing everything as a reduction 
was the fad before comprehensions came along ;-)

from functools import reduce
w = [1, 2, 3, 1, 2, 4, 4, 5, 6, 1]
def update(dic, n):
     "Mutate and return dic (contrary to usual Python policy)"
     dic[n] = dic.get(n, 0) + 1
     return dic
counts = reduce(update, w, {})
print(counts == {1: 3, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1})

# prints True

The above is how to rewrite your code in a functional language that does 
not have statements and explicit iteration. In Python, I would only 
bother to wrap the body of the loop in a function if I needed the same 
body in multiple places.

Comprehensions are filtered mappings and that both filter and map can be 
written as reduction, so reduction included comprehension. It is more 
powerful because it can also do sequential interaction. Indeed, I would 
say that it should only be used when there is sequential interaction.

-- 
Terry Jan Reedy




More information about the Python-list mailing list