9

Python 文档这样说*并且/具有相同的优先级。
我知道python中的表达式是从左到右计算的。

我可以依靠它并假设这j*j/m总是等于(j*j)/m 避免括号吗?
如果是这种情况,我可以假设这适用于具有相同优先级的运算符吗?


ps:这个问题对我的目的来说很好,我是在阅读没有括号的纯整数代码(如上面的例子)时提出的,当时这对我来说很可疑。

4

3 回答 3

14

是 - 具有相同优先级的不同运算符是左关联的;即对最左边的两项进行操作,然后是结果和第三项,以此类推。

一个例外是**运算符:

>>> 2 ** 2 ** 3
256

此外,比较运算符(==,>等)不以关联方式表现,而是转换x [cmp] y [cmp] z(x [cmp] y) and (y [cmp] z).

于 2010-07-25T06:56:20.463 回答
13

但是,如果它对你(编码人员)来说是模棱两可的,而且一定是因为你必须问,那么期望它至少对读者来说是模棱两可的,并且为了清楚起见浪费了几个八位字节。

如果您碰巧是一名编译器,那么依赖优先级规则非常有用。

添加了对评论的回复

对于遇到需要外部咨询以确保歧义的代码阅读者,您应该假设下一个读者将不如您精明,并为他们节省解析相同结构并为他们添加括号的努力和可避免的人为错误。

碰巧的是,即使是接受的答案也是不正确的(在基本原理上,而不是效果,请参阅它的第一条评论),我不知道这一点,支持它的人中也没有一小部分。

至于关于基本代数的陈述,OP中使用的特定示例具有指导意义。无论运算符优先级如何,表达式j * (j / m)在代数上都与(j * j) / m. 不幸的是,Python 代数只是“柏拉图理想”代数的近似值,根据 和 的大小,这两种形式都可能产生不正确的j答案m。例如:

>>> m = 1e306
>>> m
1e+306
>>> j = 1e307
>>> j
9.9999999999999999e+306
>>> j / m
10.0
>>> j*j
inf
>>> j * (j / m)
1e+308
>>> (j * j) / m
inf
>>> ((j * j) / m) == (j * (j/m))
False

因此,Python(和我的 FPU)准代数的身份属性确实不成立。这在您的机器上可能会有所不同,因为文档说明

浮点数是在 C 中使用 double 实现的。除非您碰巧知道您正在使用的机器,否则所有对它们精度的赌注都是关闭的。

可以说,一个人在溢出的毛茸茸的边缘没有业务,这在某种程度上是正确的,但从上下文中删除,该表达式在一种操作顺序下是不确定的,而在另一种操作顺序下是“正确的”。

于 2010-07-25T07:29:10.640 回答
3

简短的回答:是的。

Python 文档说明如下

同一框中的运算符具有相同的优先级。除非明确给出语法,否则运算符是二元的。同一框中的运算符从左到右分组(除了比较,包括测试,它们都具有相同的优先级和从左到右的链......和取幂,从右到左分组)。

因此,换句话说,您的问题的答案是肯定的,具有相同优先级的运算符将从左到右分组,而不是Comparisions which chain而不是 group

>>> x = 0
>>> y = 0
>>> x == y == True
False
>>> (x == y) == True
True
>>> x == (y == True)
True

和指数:

>>> 2 ** 2 ** 3
256
>>> (2 ** 2) ** 3
64
>>> 2 ** (2 ** 3)
256

此外,在赋值中,在左侧之前评估右侧:

>>> x = 1
>>> y = x = 2
>>> y
2
于 2010-07-25T07:20:11.907 回答