本文表格对Python中运算符的优先顺序进行了总结,从最高优先级(最先绑定)到最低优先级(最后绑定)。相同单元格内的运算符具有相同优先级。除非句法显式地给出,否则运算符均指二元运算。
相同单元格内的运算符均从左至右分组。但是,小部分运算符是从右至左分组运算,如赋值运算、幂运算、逻辑非运算、位与运算、位非运算、符号运算、条件表达式,右侧会先于左侧被求值,具体列表可参考下表“结合性”一列说明。
优先级和结合性是Python表达式中比较重要的两个概念,它们决定了先执行表达式中的哪一部分,详细说明如下:
注意,比较、成员检测和标识号检测均为相同优先级,并具有从左到右串连特性。
Python运算符列表
运算符 | 描述 | 结合性 |
---|---|---|
(expressions...) [expressions...] {key:value ...} {expressions...} |
绑定或元组显示、列表显示、字典显示、集合显示 提示,绑定即分组的意思,就是把多个运算符绑定在一起,通过分组实现优先运算 |
无 |
x[index] x[index:index] x(arguments...) x.attribute |
下标、切片、函数调用、属性引用,x表示对象 | 左 |
await x | await表达式 | 左 |
** | 指数、乘方。注意,幂操作符**比其右侧的一元算术或位操作符号优先级弱,如2**-1是0.5。 | 右 |
~ + - | 按位取反(位非,NOT布尔运算)、一元加(正)、一元减 (负) | 右 |
* @ / // % | 乘、矩阵乘法、除、取模和整除。 注意,%操作符也用于字符串格式化;适用相同的优先级。 |
左 |
+ - | 加法、减法 | 左 |
>> << | 右移位、左移位 | 左 |
& | 位与(AND'布尔运算) | 右 |
^ | 位异或 | 左 |
| | 位或(OR'布尔运算) | 左 |
in not in is is not < <= > >= != == |
比较,包括成员资格测试和身份测试 | 左 |
not | 布尔NOT | 右 |
and | 布尔AND | 左 |
or | 布尔OR | 左 |
if - else | 条件表达式 | 右 |
lambda | lambda表达式,创建匿名函数 | 左 |
:= | 赋值 | 右 |
Python 运算符优先级
所谓优先级,就是当多个运算符同时出现在一个表达式中时,先执行哪个运算符。
例如,对于表达式a + b * c
,Python 会先计算乘法再计算加法;b * c
的结果为 8,a + 8
的结果为 24,所以 d 最终的值也是 24。先计算*
再计算+
,说明*
的优先级高于+
。
我们再尝试分析下面表达式的结果:
4+4<<2
+
的优先级高于<<
,所以先执行 4+4,得到结果 8,再执行 8<<2,得到结果 32,这也是整个表达式的最终结果。
像这种不好确定优先级的表达式,我们可以给子表达式加上( )
,也就是写成下面的样子:
(4+4) << 2
这样看起来就一目了然了,不容易引起误解。
当然,我们也可以使用( )
改变程序的执行顺序,例如:
4+(4<<2)
则先执行 4<<2,得到结果 16,再执行 4+16,得到结果20。
虽然Python运算符存在优先级的关系,但不推荐过度依赖运算符的优先级,这会导致程序的可读性降低。因此建议:
- 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,可以尝试把它拆分书写。
- 不要过多地依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,应尽量使用
( )
来控制表达式的执行顺序。
Python 运算符结合性
所谓结合性,就是当一个表达式中出现多个优先级相同的运算符时,先执行哪个运算符:先执行左边的叫左结合性,先执行右边的叫右结合性。
例如,对于表达式对于100 / 25 * 16
,/
和*
的优先级相同,应该先执行哪一个呢?这个时候就不能只依赖运算符优先级决定了,还要参考运算符的结合性。/
和*
都具有左结合性,因此先执行左边的除法,再执行右边的乘法,最终结果是 64。
Python 中大部分运算符都具有左结合性,也就是从左到右执行。只有 ** 乘方运算符、单目运算符(如 not 逻辑非运算符)、赋值运算符和三目运算符例外,它们具有右结合性,也就是从右向左执行。上表列出了所有 Python 运算符的结合性。
小结
当一个表达式中出现多个运算符时,Python 会先比较各个运算符的优先级,按照优先级从高到低的顺序依次执行;当遇到优先级相同的运算符时,再根据结合性决定先执行哪个运算符:如果是左结合性就先执行左边的运算符,如果是右结合性就先执行右边的运算符。