5

I just tried a list comprehension like this

[i if i==0 else i+100 for i in range(0,3)]

and it worked, but when I tried a similar dict comprehension, it throws an error:

d={3:3}
{d[i]:0 if i==3 else d[i]:True for i in range(0,4) }

What could be the reason? How can I use dict comprehension using if else?

The error this produces:

    {d[i]:0 if i==3 else d[i]:True for i in range(0,4) }
                             ^
SyntaxError: invalid syntax

Note: The example I used here is just a random one, not my actual code. I can do this with alternative an solution, but I'm only looking at dict comprehensions now to learn.

Ilya V. Schurov
  • 7,687
  • 2
  • 40
  • 78
syam
  • 387
  • 4
  • 19

2 Answers2

13

You are using a conditional expression. It can only be used in places that accept expressions.

In a dictionary comprehension, the key and value parts are separate expressions, separated by the : (so the : character is not part of the expressions). You can use a conditional expression in each one of these, but you can't use one for both.

You only need to use it in the value part here:

{d[i]: 0 if i == 3 else True for i in range(4)}

However, you'll get a KeyError exception because the d dictionary has no 0, 1, and 2 keys.

See the Dictionary displays section of the expression reference documentation:

dict_display       ::=  “{” [key_datum_list | dict_comprehension] “}”
[...]
dict_comprehension ::=  expression “:” expression comp_for

[...]

A dict comprehension, in contrast to list and set comprehensions, needs two expressions separated with a colon followed by the usual “for” and “if” clauses.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • But So I can't use list comprehension if my declared dict dont have the keys? like you mentioned "However, you'll get a KeyError exception because the d dictionary has no 0, 1, and 2 keys" ? – syam Sep 16 '17 at 14:17
  • @syam: what has this got to do with a list comprehension? You have an expression defining the key, `d[i]`. That expression will fail for `i = 0`, there is no `d[0]`. Only `d[3]` exists. – Martijn Pieters Sep 16 '17 at 14:18
  • Compare this to a regular `for` loop: first `result = {}`, then `for i in range(4):`, and in the loop body `key = d[i]`, `value = 0 if i == 3 else True`, `result[key] = value`. That's exactly what the dict comprehension does, but without the names `result`, `key` and `value` actually being used. `key = d[i]` fails because there is no `d[0]`. – Martijn Pieters Sep 16 '17 at 14:19
  • Thanks Buddy!. well explanation – syam Sep 16 '17 at 14:23
5

Another solution for dict comprehension with if-else problem:

dict((x, x ** 2) if x > 0 else (x, -x ** 2) for x in range(-4, 5))
Ilya V. Schurov
  • 7,687
  • 2
  • 40
  • 78