Python运算符大全:七大类用法、优先级与结合性详解
一、算术运算符(Arithmetic Operators)
算术运算符负责执行常规数学运算。Python 支持 7 种标准的算术运算符:加法(+)、减法(-)、乘法(*)、真除法(/)、整除(//)、求模(%)以及幂运算(**)。
# 算术运算基础示例
a = 15
b = 4
print("加法 a + b =", a + b) # 19
print("真除法 a / b =", a / b) # 3.75(即便能整除,结果始终为浮点数)
print("整除 a // b =", a // b) # 3(向下取整)
print("取模 a % b =", a % b) # 3(余数)
print("幂运算 a ** 2 =", a ** 2) # 225
整除与取模的负数边界
Python 的整除 // 采用向下取整(Floor Division)规则,即向负无穷方向取最接近的整数,而不是向零截断。这也直接决定了模运算 % 的符号与被除数和除数的关系:在 Python 中,a % b 的结果符号始终与除数 b 的符号保持一致,满足等式 a = (a // b) * b + (a % b)。
# 负数整除与取模
print(-7 // 2) # 输出: -4 (向负无穷取整,而非 -3)
print(-7 % 2) # 输出: 1 (计算公式: -7 - (-4 * 2) = 1)
print(7 // -2) # 输出: -4
print(7 % -2) # 输出: -1 (符号与除数 -2 保持一致)
二、比较运算符(Comparison Operators)
比较运算符用于评估两个值之间的关系,运算结果始终为布尔值 True 或 False。包含:等于(==)、不等于(!=)、大于(>)、小于(<)、大于等于(>=)以及小于等于(<=)。
独特的链式比较机制
与其他诸多语言不同,Python 提供了直观的链式比较语法。例如表达式 1 < x < 10 在 Python 中是完全合法的,它等价于 (1 < x) and (x < 10)。更重要的是,在链式比较中,位于中间的操作数只会被求值一次,这避免了因函数调用产生的副作用或重复计算。
def get_val():
print("函数 get_val 被执行")
return 5
# 链式比较:中间表达式仅计算一次
if 0 < get_val() <= 10:
print("值处于区间 (0, 10] 内")
# 示例输出:
# 函数 get_val 被执行
# 值处于区间 (0, 10] 内
三、赋值运算符与海象运算符(Assignment Operators)
赋值运算符用于将右侧的值赋予左侧的变量。除了基础赋值号 = 之外,Python 提供了复合赋值运算符(如 +=, -=, *=, /=, //=, %=, **=, &=, |= 等)。
可变对象与不可变对象的复合赋值差异
对于不可变对象(如 int、str、tuple),复合赋值 a += b 会创建新的对象并重新绑定变量;但对于可变对象(如 list),+= 会优先调用对象的 __iadd__ 方法,在原内存地址上直接就地修改(In-place Modification)。
# 不可变对象:重新绑定新内存
x = 10
old_id = id(x)
x += 1
print(id(x) == old_id) # False,产生了新的整数对象
# 可变对象:就地修改同一对象
lst1 = [1, 2]
old_lst_id = id(lst1)
lst1 += [3]
print(id(lst1) == old_lst_id) # True,原列表被就地扩充
海象运算符(:=)
Python 3.8 引入了海象运算符(Assignment Expression,语法 name := expr)。它允许在表达式内部同时完成赋值与求值,能够显著减少多余的变量初始化或重复的函数调用。
# 使用海象运算符精简逻辑
sample_text = "Python Programming"
# 在 if 语句内部赋值并判断
if (n := len(sample_text)) > 10:
print(f"文本较长,长度为: {n}")
# 在循环读取数据时尤为高效
# while (chunk := stream.read(1024)):
# process(chunk)
四、逻辑运算符与短路求值(Logical Operators)
Python 的逻辑运算符包括 and(逻辑与)、or(逻辑或)和 not(逻辑非)。在 Python 中,任何对象都可以参与布尔判定(如 0、""、[]、None 等等价于假值 False,其余多数为真值 True)。
短路求值与真实返回值特性
Python 的 and 和 or 运算符具备两个非常核心的特征:
- 短路求值(Short-circuit Evaluation):一旦左侧操作数能够确定整体表达式的结果,右侧操作数将完全不会被执行。
- 返回决定性操作数:
and和or并不强制返回布尔字面量True或False,而是返回最终决定该逻辑结果的操作数本身。
五、位运算符(Bitwise Operators)
位运算符直接作用于整数的二进制补码形式。Python 支持 6 种位运算符:按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)与右移(>>)。
| 运算符 | 名称 | 运算规则 | 示例 (以 a=5: 0101b, b=3: 0011b 为例) |
|---|---|---|---|
& |
按位与 | 两位均为 1 时结果为 1,否则为 0 | 5 & 3 得到 1 (0001b) |
| |
按位或 | 任意一位为 1 时结果为 1,否则为 0 | 5 | 3 得到 7 (0111b) |
^ |
按位异或 | 两位不同为 1,相同为 0 | 5 ^ 3 得到 6 (0110b) |
~ |
按位取反 | 将各位翻转(公式:~x = -(x + 1)) |
~5 得到 -6 |
<< |
左移 | 各二进制位向左移动指定位数,低位补0(等价于乘以 2n) | 5 << 1 得到 10 (1010b) |
>> |
右移 | 各二进制位向右移动指定位数(等价于整除 2n) | 5 >> 1 得到 2 (0010b) |
在工程中,位运算符广泛用于权限掩码设计与高频状态位压缩。例如 Linux 风格的文件读写执行权限(R=4, W=2, X=1),可以通过 perm & 4 快速判定是否具备读权限。
六、成员与身份运算符(Membership & Identity Operators)
这两类运算符是 Python 中表达语义非常强、但也是初学者最容易产生混淆的操作符。
1. 成员运算符(in / not in)
成员运算符用于测试序列或集合结构中是否存在指定元素。需要特别注意数据结构带来的性能差异:
- 在
list、tuple、str中使用in,时间复杂度为 O(n),底层为线性遍历。 - 在
set或dict中使用in,时间复杂度为 O(1),底层基于哈希表寻址。因此在大规模数据检索场景下,应优先转换为集合进行判断。
2. 身份运算符(is / is not)与等于号(==)的底层区别
很多开发者容易将 is 与 == 混用,二者的判断基准完全不同:
==(相等性):比较两个对象保存的值是否相等,通过调用对象的__eq__()方法判定。is(同一性):比较两个变量是否引用内存中同一个对象,即id(a) == id(b)。
在 Python 中,单例对象(如
None)在内存中有且仅有一处实例。判断一个变量是否为 None,必须遵循 PEP 8 规范写作 if x is None:,绝对不要写作 if x == None:。因为 == 会触发类内部的 __eq__ 重载逻辑,既降低效率,又可能因为第三方类的异常重载产生错误判定。
七、运算符优先级与结合性完全指南
当一个复杂表达式中包含多个不同类别的运算符时,表达式的计算顺序取决于两个核心规则:
- 优先级(Precedence):优先级高的运算符先执行,优先级低的后执行(例如乘法优先于加法)。
- 结合性(Associativity):当多个运算符具有完全相同的优先级时,决定从左到右还是从右到左进行计算。
Python 运算符优先级总表(从高到低)
| 优先级 | 运算符 | 描述 | 结合性 |
|---|---|---|---|
| 1(最高) | ( ), [ ], { }, ., f(x) |
括号、下标切片、属性访问、函数调用 | 从左到右 |
| 2 | ** |
幂运算 | 从右到左(右结合) |
| 3 | +x, -x, ~x |
一元正负号、按位取反 | 从右到左 |
| 4 | *, /, //, % |
乘法、真除、整除、取模 | 从左到右 |
| 5 | +, - |
二元加法、减法 | 从左到右 |
| 6 | <<, >> |
二进制左移、右移 | 从左到右 |
| 7 | & |
按位与 | 从左到右 |
| 8 | ^ |
按位异或 | 从左到右 |
| 9 | | |
按位或 | 从左到右 |
| 10 | ==, !=, <, >, <=, >=, is, in |
比较、身份测试、成员测试 | 特殊(链式组合) |
| 11 | not |
逻辑非 | 从右到左 |
| 12 | and |
逻辑与 | 从左到右 |
| 13 | or |
逻辑或 | 从左到右 |
| 14 | if ... else |
三元条件表达式 | 从右到左(右结合) |
| 15(最低) | :=, =, +=, -= 等 |
海象赋值、变量赋值与复合赋值 | 从右到左(右结合) |
右结合运算符的深度剖析
绝大多数算术与位运算符都遵循左结合规则(例如 10 - 4 - 2 等价于 (10 - 4) - 2 = 4)。但 Python 中有三类至关重要的右结合(Right-associative)运算符:
1. 幂运算符(**):
# 幂运算从右往左结合
res = 2 ** 3 ** 2
# 正确计算逻辑:2 ** (3 ** 2) = 2 ** 9 = 512
# 错误理解(左结合):(2 ** 3) ** 2 = 8 ** 2 = 64
print(res) # 输出: 512
2. 三元条件表达式(x if c else y):
# 条件表达式嵌套也是从右向左结合
a = 1
b = 2
res = "A" if a == 1 else "B" if b == 2 else "C"
# 等价于: "A" if a == 1 else ("B" if b == 2 else "C")
print(res) # 输出: A
3. 链式赋值(=):
# 链式赋值从右向左依次赋值
x = y = z = 100
# 先将 100 赋给 z,再将 z 赋给 y,最后赋给 x
八、常见工程陷阱与避坑清单
1. 位运算与比较运算的优先级陷阱
在所有优先级陷阱中,最隐蔽、最致命的是比较运算符高于位运算符。例如很多开发者直觉上认为 a & mask != 0 会先计算 a & mask,但根据优先级表,!= 的优先级高于 &,因此它实际上被解析为 a & (mask != 0),从而导致完全不可预期的逻辑漏洞。
val = 6 # 二进制: 0110
mask = 2 # 二进制: 0010
# 错误写法:!= 优先于 & 计算
wrong = val & mask != 0
# 实际执行: val & (mask != 0) -> 6 & True -> 6 & 1 = 0 -> 结果为 0 (假值)
# 正确写法:加括号明确意图
correct = (val & mask) != 0 # True
2. 浮点数比较规避 ==
计算机内部使用二进制 IEEE 754 标准存储浮点数,很多十进制小数无法精确表示。因此在计算过程中,永远不要使用 == 直接比较浮点数,应使用标准库函数 math.isclose()。
import math
a = 0.1 + 0.2
print(a == 0.3) # False (内部实际为 0.30000000000000004)
print(math.isclose(a, 0.3)) # True (设置容差范围内视为相等)
3. 链式赋值共享可变对象引用
使用 a = b = [] 初始化列表时,两个变量实际上指向了同一内存列表对象。修改 a 会直接导致 b 也发生变化。初始化可变对象应始终分行独立声明:
# 陷阱:共享同一可变容器
list_a = list_b = []
list_a.append(1)
print(list_b) # 输出: [1],非预期共享!
# 正确做法:分别创建独立实例
list_a = []
list_b = []
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









