Franci Franci - 2 months ago 16
Python Question

python comprehension trubleshooting

base=2
digits=set(range(base))
key=range(base**3)
dict={ k:[a,b,c] for k in key for a in digits for b in digits for c in digits}
print(dict)


the output is:

{0: [1, 1, 1], 1: [1, 1, 1], 2: [1, 1, 1], 3: [1, 1, 1], 4: [1, 1, 1], 5: [1, 1, 1], 6: [1, 1, 1], 7: [1, 1, 1]}


I wonder why the output for [a,b,c] is [1,1,1], not the same as the:

[[a,b,c] for a in digits for b in digits for c in digits]


which is:

[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1],[1,1,0], [1, 1, 1]]

Answer

We can simplify the dictionary comprehension to something like:

In [728]: {k:[a,b] for k in [1,2] for a in [1,2] for b in [1,2]}
Out[728]: {1: [2, 2], 2: [2, 2]}

It is the equivalent to constructing a dictionary with nested loops:

In [731]: d={}
In [732]: for k in [1,2]:
     ...:     for a in [1,2]:
     ...:         for b in [1,2]:
     ...:             d[k]=[a,b]
     ...:             
In [733]: d
Out[733]: {1: [2, 2], 2: [2, 2]}

But to clarify what is going, let's use a defaultdict, and append the new values:

In [730]: from collections import defaultdict
In [734]: d=defaultdict(list)
In [735]: for k in [1,2]:
     ...:     for a in [1,2]:
     ...:         for b in [1,2]:
     ...:             d[k].append([a,b])
     ...:             
In [736]: d
Out[736]: 
defaultdict(list,
            {1: [[1, 1], [1, 2], [2, 1], [2, 2]],
             2: [[1, 1], [1, 2], [2, 1], [2, 2]]})

It is writing each [a,b] pair to the dictionary, but you only end up seeing the last pair for each key.

And yes, @user2357112's comprehension does the same thing

In [737]: {k:[[a,b] for a in [1,2] for b in [1,2]] for k in [1,2]}
Out[737]: {1: [[1, 1], [1, 2], [2, 1], [2, 2]], 2: [[1, 1], [1, 2], [2, 1], [2, 2]]}
Comments