14

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?

3 Answers 3

23

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)
Sign up to request clarification or add additional context in comments.

2 Comments

Good ol' "comma operator has lower precedence than the conditional ternary"... Even works in C...
Any method to do his when doing it as a list? Just returns a single list of length 2 tuples when I use brackets instead of two separate lists.
2

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)

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.