Page 1 of 1

Odd Python parsing?

Posted: Wed Aug 14, 2019 5:22 am
by pythoncoder
Apologies for raising something which isn't MicroPython specific. The following is a rare instance of a simple piece of Python code whose behaviour surprised me. I wondered what others think. MicroPython and cPython behave similarly. Consider:

Code: Select all

def foo(bar):
    print((1, 2) if bar else 3, 4)
If passed False it produces 3, 4 which was my expectation. If passed True it produces (1, 2) 4 which I find bizarre. The parser's interpretation of the comma between 3, 4 evidently depends on the state of bar. Is this really to be expected?

The workround is simply to make 3, 4 a tuple.

Re: Odd Python parsing?

Posted: Wed Aug 14, 2019 5:45 am
by jimmo
The rules work out such that the expression is equivalent to:

Code: Select all

print(((1, 2,) if bar else 3), 4)
So you either get

Code: Select all

print((1, 2,), 4) # (1, 2) 4
or
print(3, 4) # 3 4
pythoncoder wrote:
Wed Aug 14, 2019 5:22 am
The parser's interpretation of the comma between 3, 4 evidently depends on the state of bar. Is this really to be expected?
As far as I can tell, it's interpreted as the argument separator for the call to print() in both cases?

Re: Odd Python parsing?

Posted: Wed Aug 14, 2019 5:59 am
by Roberthh
Peter, why should that be bizarre. In your example, print has two parameters:
(1, 2) if bar else 3
4
So it will print, depending on bar, (1, 2) or 3, and it will always print 4. So this is more an example on how ternary expression can create hard-to-read code. Although, I like to use them, but most of the time in simple assignments.

Re: Odd Python parsing?

Posted: Wed Aug 14, 2019 7:44 am
by pythoncoder
It isn't related to the print statement. You get the same outcome without it:

Code: Select all

>>> bar = False
>>> z = (1, 2) if bar else 3, 4
>>> z
(3, 4)
>>> bar = True
>>> z = (1, 2) if bar else 3, 4
>>> z
((1, 2), 4)
>>> 

Re: Odd Python parsing?

Posted: Wed Aug 14, 2019 7:53 am
by jimmo
pythoncoder wrote:
Wed Aug 14, 2019 7:44 am
It isn't related to the print statement.
Right, in this case it's the separator for a tuple expression. But the parser still handles the comma the same way, regardless of the value of bar. It's the same as:

Code: Select all

>>> bar = False
>>> x = (1, 2) if bar else 3
>>> z = x, 4
>>> z
(3, 4)
>>> bar = True
>>> x = (1, 2) if bar else 3
>>> z = x, 4
>>> z
((1, 2), 4)
>>> 

Re: Odd Python parsing?

Posted: Wed Aug 14, 2019 11:54 am
by pythoncoder
jimmo wrote:
Wed Aug 14, 2019 7:53 am
...the parser still handles the comma the same way...
Right, got it! Thanks.