Python运算符优先级
定义
一个表达式里出现多个运算符时,需要一套规则决定先算哪一部分。优先级决定不同级别运算符的先后,优先级高的先结合;结合性决定同一优先级的运算符如何分组。括号可以强制改变默认顺序,写在括号里的部分总是先算。
下表按优先级从高到低排列,同一行的运算符优先级相同:
| 运算符 | 描述 | 示例或备注 |
|---|---|---|
(...)、[...]、{...} | 括号、列表、字典与集合的显示 | 优先级最高 |
x[i]、x[i:j]、x.attr、f(...) | 下标、切片、属性、函数调用 | |
** | 幂运算 | 2**3**2等于2**(3**2) = 512,右结合 |
~、+x、-x | 按位取反、正负号 | 一元运算符 |
*、/、//、% | 乘、除、整除、取模 | // 向下取整 |
+、- | 加、减 | |
<<、>> | 移位 | |
& | 按位与 | |
^ | 按位异或 | |
| | 按位或 | |
in、not in、is、is not、<、<=、>、>=、!=、== | 比较运算符 | 优先级相同,支持链式比较a < b < c |
not | 逻辑非 | |
and | 逻辑与 | 短路:False and x不计算x |
or | 逻辑或 | 短路:True or x不计算x |
if–else | 条件表达式 | x if c else y |
lambda | Lambda表达式 | |
:= | 海象运算符,Python 3.8+ | 优先级最低 |
这张表只适用于Python。C使用不同的运算符集合与优先级,参见C运算符优先级。
性质
同级运算的结合方向
同一行的运算符一般从左到右结合,例如10 - 3 - 2先算10 - 3,再减2。幂运算 ** 是主要例外,从右到左结合,所以连写多个 ** 时要从最右边的一组算起。
结合方向只决定分组,不改变优先级:2 * 3 ** 2先算幂再算乘法,因为 ** 的优先级更高。
括号改变求值顺序
括号内的表达式整体先算,再参与外层运算。表里的顺序只是“不加括号时的默认分组”;需要别的顺序时加括号即可,不必背下整张表再心算。
逻辑运算的短路
and与or从左到右求值,一旦结果已经确定就停下来:
and左边为假时,右边不再计算,结果就是左边的值;or左边为真时,右边不再计算,结果就是左边的值。
短路不只是省时间:右边如果带副作用或会抛异常,短路时这些代码根本不会执行。例如True or 1 / 0不会触发ZeroDivisionError。
比较运算可以链式书写
比较运算符优先级相同,并且支持链式写法:a < b < c等价于a < b and b < c,中间的操作数只求值一次。它不表示先算a < b再把布尔结果与c比较。
易错点
例子
幂与一元负号:-3**2
** 的优先级高于一元负号,-3**2先算3**2 = 9,再取负,结果是 -9。想要 必须写成 (-3)**2。
幂运算右结合:2**3**2
** 从右到左结合,2**3**2等价于2**(3**2) = 2^9 = 512,而不是 (2**3)**2 = 64。
比较先于逻辑非:not a == b
比较运算符的优先级高于not,所以not a == b等价于not (a == b)。如果本意是先取反再比较,必须写成 (not a) == b。
and先于or:a and b or c
and的优先级高于or,所以a and b or c等价于 (a and b) or c:先求a and b,结果再与c做or。
在解释器里核对分组
print(2 ** 3 ** 2) # 512print(-3 ** 2) # -9print(not 1 == 2) # Trueprint(True or 1 / 0) # True,右侧没有被求值探索
负号和幂运算怎样分组?
改变指数,比较负号在括号内外的结果。
正在准备演示…
练习
-3**2的值是 。参考解答
**优先于一元负号,先算3**2 = 9,再取负得到-9。2**3**2的值是 。参考解答
幂运算右结合,等价于
2**(3**2) = 2^9 = 512。not 1 == 2的结果是:参考解答
比较先算,
1 == 2为False,再取非得到True。True and False or True的结果是:参考解答
and先算,True and False为False,再与True做or,结果为True。关于
and、or的求值,下列说法正确的是:参考解答
短路规则使A、B成立;表中
and高于or,C成立。比较运算符的优先级高于not、and、or,D不成立。