为什么'not(True) * True'有效的语法,不像"True * not(True)"?



这是Python中运算符层次顺序的结果吗?

not(True) * True
# False
True * not(True)
# SyntaxError: invalid syntax

这是Python中运算符层次顺序的结果吗?

是(尽管通常的术语是运算符优先级(。总结与简化:

  1. not不是一个函数;它是运算符。因此,我们不需要为not (True)写括号,事实上它们在这里什么都不做。所发生的一切是,括号被视为普通的分组括号-(True)在其他任何东西之前被求值,成为True。所以,让我们考虑一下没有括号的例子。

  2. CCD_ 5是指CCD_。由于运算符的优先级,它不是指(not True) * True。这是经过设计的:

    >>> not 1 * 0
    True
    >>> not (1 * 0)
    True
    >>> (not 1) * 0
    0
    

    开发人员认为,编写类似not 1 * 0的内容并获得整数结果是出乎意料的,在数学运算之前编写not并使not仅适用于该表达式中的第一个内容也是出乎意料的。

  3. 由于相同的运算符优先级,True * not True是一个语法错误。Python将not本身解析为*的右侧,因为它还没有将not True组合在一起。CCD_ 15显然是无稽之谈。或者,从另一个角度来看:;CCD_ 16后面跟着表达式";不在";可以是CCD_ 17"的操作数的事物;。

    这可能令人惊讶,因为其他常用的一元运算符-(即一元否定(没有这个问题。但这是因为优先级是相反的:一元否定是在乘法之前处理的,而不是在乘法之后。

    andor组合也是如此:

    >>> 3 * 5 and 1 # 3 * 5 is evaluated first
    1
    >>> 3 * (5 and 1)
    3
    >>> 3 or 1 * 5 # 1 * 5 is evaluated first, even though it comes later
    3
    >>> (3 or 1) * 5
    15
    

这是一个优先级问题,以及优先级是如何实现的。

*具有比not更高的优先级,并且在Python语法中工作的方式是存在表达式类型的层次结构,其结构使得更高优先级的运算符可以是"0";根";参数的运算符转换为优先级较低的运算符,但不能反过来。

例如,乘法表达式的语法规则是

term[expr_ty]:
| a=term '*' b=factor { _PyAST_BinOp(a, Mult, b, EXTRA) }
| a=term '/' b=factor { _PyAST_BinOp(a, Div, b, EXTRA) }
| a=term '//' b=factor { _PyAST_BinOp(a, FloorDiv, b, EXTRA) }
| a=term '%' b=factor { _PyAST_BinOp(a, Mod, b, EXTRA) }
| a=term '@' b=factor { CHECK_VERSION(expr_ty, 5, "The '@' operator is", _PyAST_BinOp(a, MatMult, b, EXTRA)) }
| factor

CCD_ 23是乘法表达式的语法规则。该规则中的前5个选项由中间的乘法后退运算符、运算符左侧的另一个term和右侧的factor组成,其中factor是下一个更高优先级运算符类的规则。第六个选项只是一个factor

这样构造语法可以确保解析的语法树始终与运算符优先级给定的结构匹配,但这也意味着较低优先级的运算符不能是";根";参数的运算符转换为优先级更高的运算符,即使表达式看起来不明确。只是没有语法规则允许not表达式作为*表达式的参数。

(大多数表达式的语法规则都遵循上面的结构,但也有例外。例如,括号的语法规则不遵循"高优先级表达式中没有低优先级运算符"的结构,这就是为什么你可以写3 * (4 + 5)之类的东西。指数是另一个例外-**比一元+/-/~绑定得更紧。(n在左边,但不在右边,因此**和一元+/-/~的规则没有遵循明确的优先级层次结构。(

最新更新