1

I am doing an assignment to compile a subset of Pascal and in the initial program there is a line of code like this:

if x.tp == y.tp in {Bool, Int}:
    some other code ...

This makes me really confused as x.tp == y.tp returns a boolean value True or False and thus True/False in {Bool, Int} will always return False.

The definition of Bool and Int is the following:

class Int: pass

class Bool: pass

Then, I set a breakpoint at that line, and play around in VSCode's debugger:

>> x.tp
<class 'ST.Int'>
>> y.tp
<class 'ST.Int'>
>> x.tp == y.tp
True
>> a = (x.tp == y.tp)
None
>> a
True
>> a in {Bool, Int}
False
>> x.tp == y.tp in {Bool, Int}
True       <----------------------- why does it return True?

Why does x.tp == y.tp in {Bool, Int} return True here?

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
齐天大圣
  • 1,169
  • 5
  • 15
  • 36

2 Answers2

4

Use parentheses to group the equality comparison:

if (x.tp == y.tp) in {Bool, Int}:

Your chained comparison gets evaluated by Python as:

if x.tp == y.tp and y.tp in {Bool, Int}:

which yields True since y.tp is of class <class 'ST.Int'> and actually in that set.

From the Reference Manual on Comparisons:

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be False).

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
  • That shouldn't matters as == and in has the same precedence and it will be evaluated from left to right isn't it? – 齐天大圣 Feb 19 '17 at 21:06
  • @Jackddddd `==` gets evaluated, `y.tp in {Bool, Int}` also gets evaluated though (since the equality is `True`) and makes the whole thing `True`, that's how Python deals with chained comparisons. – Dimitris Fasarakis Hilliard Feb 19 '17 at 21:10
0

Naturally, we're of the assumption that this line of code

if x.tp == y.tp in {Bool, Int}:

should work (or parsed) like:

if (x.tp == y.tp) in {Bool, Int}:

But this is not the case. According to this article, the parsing and then the comparison is done like:

if (x.tp == y.tp) and (y.tp in {Bool, Int}) :

There's something confusing going on because of not being explicit. Please try to avoid similar situations for the benefit of the code maintainer.

Source: Python comparison operators chaining

kmario23
  • 57,311
  • 13
  • 161
  • 150