运算符
Python 2 的运算符覆盖了算术、比较、赋值、逻辑、位运算等多个维度。理解它们的优先级和行为边界,是写出正确代码的基础。
算术运算符
a, b = 17, 3
print a + b # 20,加法
print a - b # 14,减法
print a * b # 51,乘法
print a / b # 5,整数除法(地板除)
print a // b # 5,地板除(与 / 结果相同)
print a % b # 2,取模(余数)
print a ** b # 4913,幂运算(17 的 3 次方)
⚠️ Python 2 中 / 的行为是最大陷阱:两个整数相除,结果截断为整数。要获得浮点结果,至少一个操作数必须是浮点数:
print 17 / 3 # 5
print 17 / 3.0 # 5.66666666667
print 17.0 / 3 # 5.66666666667
print float(17) / 3 # 5.66666666667
如果希望 / 始终执行真除法(与 Python 3 一致),可以导入未来特性:
from __future__ import division
print 17 / 3 # 5.66666666667
print 17 // 3 # 5,地板除仍然可用
取模运算符 % 的结果符号与除数一致:
print 17 % 3 # 2
print -17 % 3 # 1(不是 -2)
print 17 % -3 # -1
这在处理循环数组索引时非常有用:index % length 始终返回非负的有效索引。
比较运算符
print 1 == 1 # True
print 1 != 2 # True
print 3 > 2 # True
print 3 >= 3 # True
print 2 < 3 # True
print 2 <= 2 # True
Python 支持链式比较,这是它相比 C 语言的优雅之处:
x = 5
print 1 < x < 10 # True,等价于 1 < x and x < 10
print 1 < x > 3 # True,等价于 1 < x and x > 3
⚠️ Python 2 允许比较不同类型的对象,结果由类型名称决定:
print 3 < "a" # True,因为 "int" < "str"(按类型名字母顺序)
print [1] > (1,) # False,因为 "list" < "tuple"
这种隐式比较极易引发 bug。Python 3 中比较不同类型会抛出 TypeError。
赋值运算符
x = 10
x += 5 # x = x + 5,15
x -= 3 # 12
x *= 2 # 24
x /= 4 # 6(整数除法)
x //= 2 # 3
x %= 2 # 1
x **= 3 # 1(1 的 3 次方)
复合赋值运算符(如 +=)对可变对象有特殊效果:
a = [1, 2]
a += [3, 4] # 等价于 a.extend([3, 4]),原地修改
print a # [1, 2, 3, 4]
b = [1, 2]
b = b + [3, 4] # 创建新列表,再赋值给 b
print b # [1, 2, 3, 4]
a += [3, 4] 和 a = a + [3, 4] 对列表来说结果相同,但前者原地修改,后者创建新对象。对不可变对象(如元组),+= 只能创建新对象。
逻辑运算符
and、or、not 是 Python 的逻辑运算符。它们的关键特性是短路求值和返回操作数本身:
print 3 and 5 # 5,不是 True
print 0 and 5 # 0,短路:0 为假,直接返回 0
print "hello" and "" # "",空字符串为假,但已经走到第二个操作数
print 3 or 5 # 3,短路:3 为真,直接返回 3
print 0 or 5 # 5,0 为假,继续判断 5
print "" or "default" # "default"
and 遇假停,or 遇真停。返回值是最后一个被评估的操作数,而非布尔值。这个特性常用于设置默认值:
name = user_input or "Anonymous" # 如果 user_input 为空字符串,用默认值
not 始终返回布尔值:
print not 0 # True
print not "" # True
print not [1, 2] # False
print not None # True
身份运算符
is 和 is not 比较两个对象的身份(内存地址),而非值:
a = [1, 2, 3]
b = [1, 2, 3]
print a == b # True,值相等
print a is b # False,不是同一个对象
c = a
print a is c # True,c 和 a 指向同一个对象
is 最常见的用途是检查 None:
if x is None:
print "x is not set"
不要用 == 检查 None,因为某些对象可能重载了 __eq__ 使其等于 None。
Python 2 对小整数(-5 到 256)有缓存机制,所以:
a = 100
b = 100
print a is b # True,小整数被缓存复用
x = 1000
y = 1000
print x is y # False,大整数创建新对象
成员运算符
in 和 not in 检查对象是否是某个容器的成员:
print 3 in [1, 2, 3] # True
print "a" in "abc" # True
print "x" not in "abc" # True
print 1 in (1, 2, 3) # True
print "a" in {"a": 1, "b": 2} # True,检查键
对于列表和元组,in 使用线性搜索,时间复杂度 O(n)。对于字典和集合,使用哈希查找,时间复杂度 O(1)。
位运算符
a, b = 0b1100, 0b1010 # 12 和 10
print a & b # 0b1000 = 8,按位与
print a | b # 0b1110 = 14,按位或
print a ^ b # 0b0110 = 6,按位异或
print ~a # -13,按位取反(补码表示)
print a << 2 # 0b110000 = 48,左移两位
print a >> 2 # 0b0011 = 3,右移两位
位运算直接操作二进制位,常用于标志位管理、权限系统、图像处理等场景。
运算符优先级
从高到低排列:
| 优先级 | 运算符 | 说明 |
|---|---|---|
| 1 | () | 括号 |
| 2 | ** | 幂运算 |
| 3 | +x, -x, ~x | 正负号、按位取反 |
| 4 | *, /, //, % | 乘除 |
| 5 | +, - | 加减 |
| 6 | <<, >> | 位移 |
| 7 | & | 按位与 |
| 8 | ^ | 按位异或 |
| 9 | | | 按位或 |
| 10 | <, <=, >, >=, ==, != | 比较 |
| 11 | is, is not, in, not in | 身份、成员 |
| 12 | not | 逻辑非 |
| 13 | and | 逻辑与 |
| 14 | or | 逻辑或 |
| 15 | =,+= 等 | 赋值 |
不确定时,用括号明确优先级:
result = (a + b) * c # 明确先加后乘