Python 负常数与运算符优先级
我已经用Python编程多年了,但一些非常琐碎的事情让我吃惊:Python 负常数与运算符优先级,python,Python,我已经用Python编程多年了,但一些非常琐碎的事情让我吃惊: -1**2 -1 当然,对任何负实数求平方都会产生一个正结果。也许Python的数学并没有完全崩溃。让我们看看它是如何解析这个表达式的: ast.dump(ast.parse('-1**2').body[0]) Expr( 值=UnaryOp( op=USub(), 操作数=BinOp( 左=Num(n=1), op=Pow(), 右=Num(n=2) ) ) ) 好的,它把它当作是我写的-(1**2)。但是为什么-前缀被视为一
-1**2
-1
当然,对任何负实数求平方都会产生一个正结果。也许Python的数学并没有完全崩溃。让我们看看它是如何解析这个表达式的:
ast.dump(ast.parse('-1**2').body[0])
Expr(
值=UnaryOp(
op=USub(),
操作数=BinOp(
左=Num(n=1),
op=Pow(),
右=Num(n=2)
)
)
)
好的,它把它当作是我写的-(1**2)
。但是为什么-
前缀被视为一个单独的一元减法运算符,而不是常量的符号
请注意,表达式-1
不是解析为常量1
的一元减法,而是解析为常量-1
:
ast.dump(ast.parse('-1').body[0])
Expr(
值=Num(n=-1)
)
这同样适用于-1*2
,尽管它在语法上与第一个表达式几乎相同
ast.dump(ast.parse('-1*2').body[0])
Expr(
value=BinOp(
左=Num(n=-1),
op=Mult(),
右=Num(n=2)
)
)
这种行为在许多语言中都很常见,包括perl、PHP和Ruby。它的行为就像文档中解释的那样: 2.4.4。数字文字 […]注意数字文字不包括符号;像
-1
这样的短语实际上是由一元运算符-
和文本1
组成的表达式
以及:
6.5。电力操作员
幂运算符比一元运算符在其上绑定得更紧密
左边[……]
另请参见中的优先级表。以下是该表中的相关部分:
运算符|说明
-------------|---------------------------------
*|乘法。。。
+x、 -x,~x |正,负,按位非
**|指数化
这解释了为什么解析树在
**
和*
示例之间不同。我认为您的第三个代码块有输入错误,应该是ast.parse('-1')
,是吗?修复了,谢谢@Blorgbeard.@RyanGovostes我怀疑这是一个优化。即使它在语义上是一个运算符,但当它看到它周围的运算符具有较低的优先级时,它会将其视为一个文本负数?在3.6.8中,它按预期工作(添加了否定的UnOp
)。我不确定为什么-1
在我包含的其他两个表达式中都没有被解析为“常数1的一元否定”。这里还有一个重要部分:“请注意,数字文字不包括符号;像-1
这样的短语实际上是由一元运算符-
和文本1
“@RyanGovostes一元运算符在乘法和求幂之间具有优先权,这就是为什么您的示例对*
和**
的效果不同的原因(请参阅我更新的答案)。Python语言可能并不完美,但不久前有人建立了它的规则,至少在这方面他们坚持为该语言设置的规则。对。我想这是@Barmar建议的,并且USub(Num)子树不断发生折叠。(但为什么不折叠整个表达式?)包含如何以及何时应用此类优化的逻辑。