为什么“not(True) * True”是有效语法,与“True * not(True)”不同?

jos*_*les 21 python syntax operator-precedence

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

not(True) * True
# False
True * not(True)
# SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

Kar*_*tel 34

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

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

  1. not不是一个函数;这是一个操作员。因此,我们不需要为 写括号not (True),事实上它们在这里没有做任何事情。所发生的只是括号被视为普通的分组括号 -(True)在其他任何事情之前被评估,成为True。因此,让我们考虑不带括号的示例。

  2. not True * True方法not (True * True)。由于运算符优先级,它并不意味着, 。(not True) * True这是设计使然:

    >>> not 1 * 0
    True
    >>> not (1 * 0)
    True
    >>> (not 1) * 0
    0
    
    Run Code Online (Sandbox Code Playgroud)

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

  3. 由于相同的运算符优先级,True * not True因此存在语法错误。Python 将not本身解析为 的右侧*,因为它尚未组合在一起not TrueTrue * not显然是无稽之谈。或者,另一种看待它的方式:“not后跟一个表达式”不在“可以作为*”的操作数的列表中。

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

    and和 的组合也是如此or

    >>> 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
    
    Run Code Online (Sandbox Code Playgroud)

  • 不紧密结合的一元运算符有点疯狂。 (5认同)
  • 看起来这个答案可能会错误地认为优先级控制评估顺序。优先级并不强制评估顺序。它只是控制什么是对什么的争论。例如,在“a + b + c * d”中,“a + b”在“c * d”之前计算,正如您通过[重载运算符](https://ideone.com/sKGkp9)所看到的。 (5认同)
  • @user2357112好吧,优先级控制评估顺序*当存在依赖性时* - 类似于在调用函数之前必须评估函数的参数。对于初学者来说很难准确且清晰。但你确实有一个很好的观点。我稍后会回顾一下。具体的“还没有机会”的措辞,我会试着想一下。 (2认同)

use*_*ica 12

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

*具有比 更高的优先级not,并且在 Python 语法中工作的方式是存在表达式类型的层次结构,其结构使得较高优先级运算符可以成为较低优先级运算符的参数的“根”运算符,但不能另一种方式。

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

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
Run Code Online (Sandbox Code Playgroud)

term是乘法表达式的语法规则。此规则中的前 5 个选项由中间的乘法优先级运算符、term运算符左侧的另一个以及factor右侧的 a 组成,其中factor是下一个更高优先级运算符类的规则。第 6 个选项只是一个factor.

像这样构造语法可以确保解析的语法树始终与运算符优先级给出的结构匹配,但这也意味着较低优先级运算符不能是较高优先级运算符的参数的“根”运算符,即使表达式会显得很明确。只是没有语法规则允许not表达式作为*表达式的参数。

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