Python 的 AST 定义了布尔表达式
BoolOp(boolop op, expr* values)
我本来希望它类似于BinOp
,具有 aleft
和 aright
值。
有人可以给我一个示例代码,其中 AST 会有多个不同于两个的值吗?
编辑:
显然x and y and z
导致三个值。所以让我改写一下:
为什么不将其建模为两个嵌套BoolOp
表达式?
Python 的 AST 定义了布尔表达式
BoolOp(boolop op, expr* values)
我本来希望它类似于BinOp
,具有 aleft
和 aright
值。
有人可以给我一个示例代码,其中 AST 会有多个不同于两个的值吗?
编辑:
显然x and y and z
导致三个值。所以让我改写一下:
为什么不将其建模为两个嵌套BoolOp
表达式?
a and b and c
被 Python 解析器认为是三元合取:
>>> e = ast.parse('''a and b and c''').body[0].value
>>> e.op
<_ast.And object at 0x254d1d0>
>>> e.values
[<_ast.Name object at 0x2d9ba50>, <_ast.Name object at 0x2d9ba90>, <_ast.Name object at 0x2d9bad0>]
尽管括号会强制它解析为递归二元连接:
>>> ast.parse('''a and (b and c)''').body[0].value.values
[<_ast.Name object at 0x2d9b990>, <_ast.BoolOp object at 0x2d9bb10>]
我不确定这是为什么。在任何情况下,BoolOp
根据 CPython 源代码中的单元测试,a 可能有不少于两个孩子。
我最初认为这将是一种优化,但后来a and b and c
完全等同于a and (b and c)
; 他们甚至生成相同的字节码:
>>> def f(a, b, c):
... return a and b and c
...
>>> def g(a, b, c):
... return a and (b and c)
...
>>> from dis import dis
>>> dis(f)
2 0 LOAD_FAST 0 (a)
3 JUMP_IF_FALSE_OR_POP 15
6 LOAD_FAST 1 (b)
9 JUMP_IF_FALSE_OR_POP 15
12 LOAD_FAST 2 (c)
>> 15 RETURN_VALUE
>>> dis(g)
2 0 LOAD_FAST 0 (a)
3 JUMP_IF_FALSE_OR_POP 15
6 LOAD_FAST 1 (b)
9 JUMP_IF_FALSE_OR_POP 15
12 LOAD_FAST 2 (c)
>> 15 RETURN_VALUE