在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