Valdogg21
Valdogg21

Reputation: 1191

Python ternary operator can't return multiple values?

I know it's frowned upon by some, but I like using Python's ternary operator, as it makes simple if/else statements cleaner to read (I think). In any event, I've found that I can't do this:

>>> a,b = 1,2 if True else 0,0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

The way I figured the ternary operator works is that it essentially builds the following:

if True:
  a,b = 1,2
else:
  a,b = 0,0

Could someone explain why my first code sample doesn't work? And, if there is one, provide a one-liner to assign multiple variables conditionally?

Upvotes: 14

Views: 3335

Answers (3)

user459872
user459872

Reputation: 24827

While the other answers have already addressed your question, This will explain a method that you can use to understand how python parsing really work.

For that, you can use ast module to print the trees of the Python abstract syntax grammar(I am using python 3.12 here). If you inspect the AST of the source a,b = 1,2 if True else 0,0 it looks like the following.

>>> import ast
>>>                                   ----------------------------------|
>>>                                   |              |
>>> print(ast.dump(ast.parse("a,b = 1,2 if True else 0,0"), indent=4))  |
Module(                       | |   | ---------------------             |
    body=[                    |  ----------------------    |            |
        Assign(                ----------------------  |   |
            targets=[                                | |   |            |
                Tuple(                               | |   |            |
                    elts=[                           | |   |            |
                        Name(id='a', ctx=Store()),---  |   |            |
                        Name(id='b', ctx=Store())],----    |            |   
                    ctx=Store())],                         |            |
            value=Tuple(                                   |            |
                elts=[                                     |            |
                    Constant(value=1), ---------------------
                    IfExp(                         |                    |
                        test=Constant(value=True), |--------------------
                        body=Constant(value=2),    |
                        orelse=Constant(value=0)), |
                    Constant(value=0)],
                ctx=Load()))],
    type_ignores=[])
>>> 

If you inspect the tree carefully(I have added few comments to understand how the AST node maps to the actual source) you can see that its's getting parsed as

a,b = 1,(2 if True else 0),0

Upvotes: 0

Michael J. Barber
Michael J. Barber

Reputation: 25052

It's just a matter of operator precedence. Consider:

>>> 1,2 if True else 0,0
(1, 2, 0)

Add parentheses as needed, and you will get it to work:

(1,2) if True else (0,0)

Upvotes: 2

tckmn
tckmn

Reputation: 59333

It's parsing that as three values, which are:

1,
2 if True else 0,
0

Therefore it becomes three values (1,2,0), which is more than the two values on the left side of the expression.

Try:

a,b = (1,2) if True else (0,0)

Upvotes: 23

Related Questions