在Python中,三个操作数的比较是如何工作的?

在Python中,三个操作数的比较是如何工作的?,python,parsing,comparison-operators,python-internals,Python,Parsing,Comparison Operators,Python Internals,你能解释一下链式比较的语法分析树是什么样子的吗 据我所知,在大多数语言中,它基于运算符关联性构造节点,因此在a

你能解释一下链式比较的语法分析树是什么样子的吗

据我所知,在大多数语言中,它基于运算符关联性构造节点,因此在
a
中,将有一个布尔值作为左操作数或右操作数


但在Python中,这种表达式几乎等同于
a
(其中
b
只计算一次)

这种转换的生成语法规则是什么?基本上,Python解释器在这种情况下是如何构造解析树的?

这里没有那么有趣,它只是让您将多个比较器附加到一个运算符:

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"
因此,只有一个
Compare
节点,具有多个运算符和比较器:

Compare(
    left=Name(id='a'),
    ops=[Gt(), Gt()],
    comparators=[Name(id='b'), Name(id='c')])
(我省略了
表达式
ctx
部分)

这使解释器可以根据需要评估比较器(例如,如果
a
为false,则不必考虑剩余的比较器)

生成的字节码使用条件跳转跳过剩余的比较:

>>> import dis
>>> dis.dis(compile('a > b > c', '', 'eval'))
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               4 (>)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_NAME                2 (c)
             14 COMPARE_OP               4 (>)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE

语法规则就是比较:expr(comp_op expr)*
“这样的表达式几乎等同于
a
a
a
完全等效,除了
b
表达式保证只计算一次(最多)。@PM2Ring yes,这就是为什么我写“几乎”的原因,如果在计算bUnderstood时没有副作用,它们是等效的。我只是为了其他读者的利益添加了我的评论。
>>> import dis
>>> dis.dis(compile('a > b > c', '', 'eval'))
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               4 (>)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_NAME                2 (c)
             14 COMPARE_OP               4 (>)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE