Reputation: 1191
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
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
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
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