Python 的 AST 定义了 bool 表达式

BoolOp(boolop op, expr* values)

我本来希望它类似于 BinOp ,带有 leftright 值。

有人可以给我一个示例代码,其中 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>]

我不确定这是为什么。在任何情况下,根据 CPython 源代码中的单元测试,BoolOp 的子代不能少于两个。

我最初认为这是一种优化,但后来 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

关于python - 什么时候 ast.BoolOp 有两个以上的值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19377963/

10-13 08:55