3
你能解释一下链式比较的语法分析树是什么样子的吗?三种操作数比较如何在Python下工作?
据我所知,在大多数语言中,它构造了基于操作符关联的节点,所以在a < b < c
中将会有一个布尔值作为左侧或右侧操作数。
但是在Python中这样的表达式几乎等于a < b and b < c
(b
只能评估一次)。
什么是这种转换的生成语法规则?基本上,在这种情况下,Python解释器是如何构造分析树的?
你能解释一下链式比较的语法分析树是什么样子的吗?三种操作数比较如何在Python下工作?
据我所知,在大多数语言中,它构造了基于操作符关联的节点,所以在a < b < c
中将会有一个布尔值作为左侧或右侧操作数。
但是在Python中这样的表达式几乎等于a < b and b < c
(b
只能评估一次)。
什么是这种转换的生成语法规则?基本上,在这种情况下,Python解释器是如何构造分析树的?
的comparison grammar是不是很有趣在这里,它只是让你添加多个比较器来操作:
comparison ::= or_expr (comp_operator or_expr)*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
所以,让我们直接问了Python语法分析器,通过使用ast
module(简单地询问了Python编译器本身只返回抽象语法树):
>>> import ast
>>> ast.dump(ast.parse('a > b > c', mode='eval'))
"Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Gt(), Gt()], comparators=[Name(id='b', ctx=Load()), Name(id='c', ctx=Load())]))"
所以存在的仅仅是单Compare
节点,多个运营商和比较S:
Compare(
left=Name(id='a'),
ops=[Gt(), Gt()],
comparators=[Name(id='b'), Name(id='c')])
(I省略Expression
和ctx
份)。
这可以让解释器根据需要评估比较器(例如,如果a < b
为假,则不必考虑其余比较器)。
所得字节码使用条件跳转跳过其余比较:
>>> 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表达式)*'。 –
“这样的表达几乎相当于'a
@ PM2Ring是的,这就是为什么我写了“几乎”他们是相等的,如果没有计算副作用b –