2

I'm wondering how Python parses:

not a < b < c

It seems to interpret this as:

not (a < b < c)

as opposed to (not a) < b < c

This question explains grouping vs chaining: Python comparison operators chaining/grouping left to right? but what are the rules for the precedence of chained comparisons?

It's strange to me that not, < and > have the same precedence, but not a < b < c parses as not (a < b < c) while -a < b < c parses as (-a) < b < c.

I tested this by evaluating not 2 > 1 > 2 in Python 2.7.

martineau
  • 119,623
  • 25
  • 170
  • 301
nonagon
  • 3,271
  • 1
  • 29
  • 42
  • `not 2 < 1 < 2` isn't being parsed as `not (2 < 1 < 2)`. Each term is processed left-to-right. The `not 2` is `False` which is the same as the numeric value `0`—so it's equivalent to `0 < 1 < 2`. – martineau Sep 10 '17 at 02:05
  • This tips was already viewed. Could be: https://stackoverflow.com/questions/25753474/python-comparison-operators-chaining-grouping-left-to-right – Mauricio Vega Sep 10 '17 at 02:21
  • What made you think `not`, `<`, and `>` had the same precedence? – user2357112 Sep 10 '17 at 02:54
  • @martineau I was using 2 > 1 > 2 not 2 < 1 < 2, and I don't think that's true about the parsing – nonagon Sep 10 '17 at 03:01
  • 1
    @user2357112 I mistook the `not in` and `is not` tests for the boolean `not` operator – nonagon Sep 10 '17 at 03:01

1 Answers1

3

Python has an Abstract Syntax Tree module to show you what's happening:

import ast
t = ast.parse('not a < b < c')
print(ast.dump(t))

It gives (cleaned up a bit):

[Expr(value=UnaryOp(
    op=Not(),
    operand=Compare(
        left=Name(id='a'),
        ops=[Lt(), Lt()],
        comparators=[Name(id='b'), Name(id='c')]
    )
))]

And indeed, the documentation says that not has lower precedence than <.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436