*
和/
的优先级相同。我知道Python表达式从左到右进行计算。您是否可以依赖于此,并假设
j*j/m
始终等于(j*j)/m
而避免使用括号?如果是这样,那么我可以假设这适用于具有相同优先级的运算符吗?注:对于我的目的来说,这个问题很好,我在阅读仅包含整数的代码(如上面的示例)时避免使用括号,这让我感到非常怀疑。
*
和/
的优先级相同。j*j/m
始终等于(j*j)/m
而避免使用括号?如果是这样,那么我可以假设这适用于具有相同优先级的运算符吗?>>> 2 ** 2 ** 3
256
此外,比较操作符 (==
, >
等) 不会像结合律那样进行操作,而是将 x [cmp] y [cmp] z
转换成 (x [cmp] y) and (y [cmp] z)
。
=
号在常规意义上也不是一个运算符;操作符优先级不适用于它。在语法上,将同一对象分配给多个目标被明确定义为多目标赋值。 - Thomas Wouters**
,例如 2**3**4
。 - Nas Banov**
是仅有的Python右结合运算符 (2)它与自己右结合是事实[1]的不起眼的结果(3)比较运算符是无结合性的... a < b < c
意味着既不是 (a < b) < c
也不是 a < (b < c)
--- 请考虑最终编辑(删除您的答案)。 - John Machiny
只被评估一次之外,其他都一样。 - Mechanical snail如果你作为编码人员对某个表达式的歧义感到困惑并需要询问,那么你就应该预料到读者也会同样感到困惑,为了增加可读性,建议添加一些括号。
如果你是编译器,依靠运算符优先级规则是很好的。
针对评论的回答:
当代码阅读者遇到需要外部协助来确认的不确定性时,你应该假设下一个读者比你更不懂,并为他们节省时间和避免可能出现的人为错误,主动添加括号以增加可读性。
实际上,即使被接受的答案也是错误的(在理论上,而非效果上,详见其第一个评论),这是我之前没有意识到的,甚至一小部分投票者也没有察觉到。
至于关于基本代数的说法,在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实现浮点数。除非您知道正在使用的机器,否则精度方面的所有赌注都将关闭。
可以说,在溢出的棘手边缘工作是毫无意义的,这在某种程度上是正确的,但在去除上下文情况后,该表达式在一种运算顺序下是不确定的,而在另一种下则是“正确的”。
+-*/
运算符的表达式中期望冗余括号是荒谬的……优先级和结合性(隐含地)在学校的代数课程中教授,不是吗?对于计算机程序员来说,这被认为是基本知识,是或否?另一方面,在项目或团队标准中强制使用括号来包围像位移、位与、位或等很少使用且在不同语言中具有不同优先级的操作应该是必需的。 - John Machin简短回答:是的。
同一方框内的运算符具有相同的优先级。除非明确给出语法,否则运算符为二元运算符。同一方框内的运算符从左到右分组(除了比较,包括测试,它们都具有相同的优先级并从左到右链接...以及指数,它们从右到左分组)。
因此,换句话说,答案是肯定的,具有相同优先级的运算符将从左到右分组,而不是比较运算符会链接而不是分组:
>>> 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
a().a, b().b = c().c
中函数调用的顺序来看到这种区别:你会看到c()
会被调用,然后获取属性c
,接着调用a()
并将a
属性赋值,最后再对b()
做同样的操作。 - Thomas Woutersx
和y
的评估顺序对分配给y
的结果很重要。实际上并不是这样。x
和y
的值从未参与赋值。y = x = 2
严格意义上意味着“将2
分配给y
和x
”,而不是“将2
分配给x
,然后将x
的结果值分配给y"
(当您涉及更复杂的赋值目标时,例如使用将自己设置为与分配给它们的不同值的属性时,可以看到这一点)。 - Thomas Wouters
from __future__ import division
?应该将/
解释为和/或更改为//
吗? - John Machin