Python 逻辑运算符与位运算符详解
一文搞懂 Python 中
and / or / not与& | ^ ~ << >>的区别、陷阱与实战用法。
前言
Python 中有两类容易混淆的运算符:逻辑运算符(and、or、not)和位运算符(&、|、^、~、<<、>>)。它们外观相似、在某些场景下"看起来"结果一样,但设计目的和工作机制完全不同。本文系统梳理两者的用法、区别与常见陷阱。
一、逻辑运算符(3 个)
| 运算符 | 含义 | 示例 |
|---|---|---|
and |
与 | True and False → False |
or |
或 | True or False → True |
not |
非 | not True → False |
1.1 短路求值
and 左边为假就不再计算右边;or 左边为真就不再计算右边:
False and print("不会执行") # 无输出
True or print("不会执行") # 无输出
常用于安全判断(先判空再取值):
if obj is not None and obj.value > 10: # obj 为 None 时不会崩溃
1.2 返回值不是布尔,而是操作数之一
这是 Python 逻辑运算符最容易踩坑的地方:
3 and 5 # 5 ← and 返回第一个假值;都真则返回最后一个
0 or "x" # 'x' ← or 返回第一个真值;都假则返回最后一个
not 3 # False ← 只有 not 恒返回布尔
利用 or 给默认值是一个常见惯用法:
name = input_name or "匿名"
1.3 真值判断规则
非布尔值参与逻辑运算时,以下值为假,其余为真:
- 数字
0、0.0 - 空序列/集合:
''、[]、{}、set()、() None
二、位运算符(6 个)
位运算符对整数的二进制位逐位操作。设 x = 0b1100(十进制 12)、y = 0b1010(十进制 10):
| 运算符 | 含义 | 示例 |
|---|---|---|
& |
按位与 | 12 & 10 → 8(0b1000) |
| |
按位或 | 12 | 10 → 14(0b1110) |
^ |
按位异或 | 12 ^ 10 → 6(0b0110) |
~ |
按位取反 | ~12 → -13 |
<< |
左移 | 12 << 1 → 24(相当于 ×2) |
>> |
右移 | 12 >> 1 → 6(相当于 ÷2) |
以 12 & 10 为例逐位推演:
1100 (12)
& 1010 (10)
------
1000 (8) ← 两位都为 1 才得 1
2.1 ~n 为什么等于 -n - 1
Python 整数按补码语义理解:取反后所有位翻转,等价于 -n - 1。例如 ~5 = -6,~12 = -13。
2.2 常见用途
n & 1 # 判断奇偶:结果 1 为奇,0 为偶
n & (n - 1) # 清除最低位的 1;结果为 0 说明 n 是 2 的幂
n ^ n # 0(任何数异或自己为 0)—— 找"只出现一次的数字"等算法题常用
n << k, n >> k # 乘 / 除 2 的幂
flags | 0b100 # 置位;flags & 0b100 测位 —— 状态标志位(位掩码)
三、两者对比
逻辑运算符 and / or / not |
位运算符 & | ^ ~ << >> |
|
|---|---|---|
| 操作对象 | 整体真值 | 二进制的每一位 |
| 短路求值 | 有 | 无(两边都会计算) |
| 返回值 | 操作数之一(not 除外) |
整数 |
| 适用类型 | 任意对象 | 仅整数(及自定义了 __and__ 等方法的类型) |
四、易混淆点与陷阱
4.1 & / | 用在布尔值上
True & False 与 True and False 结果一样,但机制不同——位运算不短路,两边永远求值:
True & False # False,结果一样,但两边都会计算
4.2 条件判断中误用位运算符
# 想短路,却用了位运算符——右边永远执行,且优先级混乱
obj is not None & obj.value > 10 # ❌ 错误用法
条件判断请老老实实用 and:
obj is not None and obj.value > 10 # ✅
4.3 pandas / NumPy 中的例外
对 DataFrame、ndarray 等向量对象做元素级布尔运算时,必须用 &、|、~(它们重载了位运算符),且要加括号:
df[(df.a > 1) & (df.b < 5)] # ✅ 位运算符 + 括号
df[df.a > 1 and df.b < 5] # ❌ 报错:真值有歧义
五、总结
and / or / not操作的是"整个值的真假":支持短路求值,返回操作数之一。& | ^ ~ << >>操作的是"二进制的每一位":不短路,返回整数。- 日常条件判断用逻辑运算符;奇偶判断、位掩码、状态位、算法题用位运算符。
- 向量库(pandas/NumPy)筛选数据时,用位运算符且记得加括号。
一句话总结:逻辑运算符判断"值是真还是假",位运算符操作"二进制每一位"——前者面向流程控制,后者面向底层计算。
浙公网安备 33010602011771号