Skip to content

Python 运算符

1. 运算符优先级

运算符描述优先级结合性
(expr...)[expr...]{key: value...}{expr...}绑定或加圆括号的表达式,列表、字典、集合18
x[i]x[i:j]x(args...)x.attribute索引、切片、调用、属性引用17
await xawait 表达式16
**[1]15
+x-x~x正,负,按位非 NOT14
*@///%乘,矩阵乘,除,整除,取余13
+-加和减12
<<>>移位11
&按位与 AND10
^按位异或 XOR9
|按位或 OR8
innot inisis not<<=>>=!===比较运算,包括成员检测和标识号检测7
not x布尔逻辑非 NOT6
and布尔逻辑与 AND5
or布尔逻辑或 OR4
if ... else ...条件表达式3
lambdalambda 表达式2
:=赋值表达式1

2. 算术运算符

2.1 基本算术运算

python
# 加减乘除
a = 10 + 5   # 15
b = 10 - 5   # 5
c = 10 * 5   # 50
d = 10 / 5   # 2.0 (总是返回浮点数)

# 整除和取余
e = 10 // 3  # 3 (向下取整)
f = 10 % 3   # 1 (取余数)

# 幂运算
g = 2 ** 3   # 8
h = 2 ** -1  # 0.5

2.2 除法的注意事项

Python 3 中的除法 / 总是返回浮点数,即使两个操作数都是整数:

python
print(10 / 5)   # 2.0,不是 2
print(9 / 2)    # 4.5

# 如果需要整数结果,使用整除
print(10 // 5)  # 2
print(9 // 2)   # 4

负数的整除向负无穷方向取整:

python
print(9 // 2)    # 4
print(-9 // 2)   # -5 (不是 -4)
print(9 // -2)   # -5
print(-9 // -2)  # 4

3. 比较运算符

3.1 链式比较

Python 支持链式比较,这是一个非常优雅的特性:

python
x = 5
# 传统写法
if x > 0 and x < 10:
    print("x is between 0 and 10")

# Python 链式比较
if 0 < x < 10:
    print("x is between 0 and 10")

# 更复杂的链式比较
a, b, c = 1, 2, 3
if a < b < c:
    print("ascending order")

3.2 身份运算符 is vs 相等运算符 ==

is 比较的是对象的身份(内存地址),== 比较的是对象的值:

python
a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a == b)  # True (值相等)
print(a is b)  # False (不是同一个对象)
print(a is c)  # True (是同一个对象)

# 对于小整数和短字符串,Python 会复用对象
x = 256
y = 256
print(x is y)  # True (小整数被缓存)

x = 257
y = 257
print(x is y)  # False (大整数不被缓存)

# 检查 None 应该使用 is
if value is None:
    print("value is None")

4. 逻辑运算符

4.1 短路求值

Python 的逻辑运算符支持短路求值:

python
# and 运算符:如果第一个为假,不会计算第二个
def expensive_operation():
    print("This is expensive")
    return True

x = False
result = x and expensive_operation()  # 不会打印 "This is expensive"

# or 运算符:如果第一个为真,不会计算第二个
x = True
result = x or expensive_operation()  # 不会打印 "This is expensive"

4.2 逻辑运算符返回值

Python 的逻辑运算符不一定返回布尔值,而是返回最后一个被求值的对象:

python
print(1 and 2)        # 2
print(0 and 2)        # 0
print(1 or 2)         # 1
print(0 or 2)         # 2
print(not 1)          # False
print(not 0)          # True

# 常用于提供默认值
name = ""
display_name = name or "Anonymous"  # "Anonymous"

name = "Alice"
display_name = name or "Anonymous"  # "Alice"

5. 位运算符

5.1 基本位运算

python
a = 60  # 0011 1100
b = 13  # 0000 1101

print(a & b)   # 12 = 0000 1100 (按位与)
print(a | b)   # 61 = 0011 1101 (按位或)
print(a ^ b)   # 49 = 0011 0001 (按位异或)
print(~a)      # -61 = 1100 0011 (按位取反)
print(a << 2)  # 240 = 1111 0000 (左移)
print(a >> 2)  # 15 = 0000 1111 (右移)

5.2 位运算的应用

python
# 判断奇偶
def is_odd(n):
    return n & 1 == 1

# 交换两个数(不推荐,可读性差)
a, b = 5, 10
a = a ^ b
b = a ^ b
a = a ^ b
print(a, b)  # 10, 5

# 判断 2 的幂
def is_power_of_two(n):
    return n > 0 and (n & (n - 1)) == 0

print(is_power_of_two(8))   # True
print(is_power_of_two(10))  # False

# 获取最低位的 1
def get_lowest_bit(n):
    return n & -n

print(bin(get_lowest_bit(12)))  # 0b100

6. 运算符重载

6.1 算术运算符重载

可以通过魔法方法重载运算符:

python
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)
    
    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)
    
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)  # Vector(4, 6)
print(v1 * 3)   # Vector(3, 6)

6.2 比较运算符重载

python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
    def __lt__(self, other):
        return (self.x ** 2 + self.y ** 2) < (other.x ** 2 + other.y ** 2)
    
    def __repr__(self):
        return f"Point({self.x}, {self.y})"

p1 = Point(1, 2)
p2 = Point(1, 2)
p3 = Point(3, 4)

print(p1 == p2)  # True
print(p1 < p3)   # True

7. 特殊运算符

7.1 海象运算符 :=

Python 3.8+ 引入的海象运算符(赋值表达式)可以在表达式中进行赋值:

python
# 传统写法
data = input("Enter something: ")
if len(data) > 10:
    print("Too long")

# 使用海象运算符
if (n := len(data := input("Enter something: "))) > 10:
    print(f"Too long: {n} characters")

# 在列表推导中使用
results = [y for x in range(10) if (y := x ** 2) > 50]
print(results)  # [64, 81]

7.2 矩阵乘法运算符 @

Python 3.5+ 引入了矩阵乘法运算符 @

python
import numpy as np

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])

# 矩阵乘法
c = a @ b
print(c)
# [[19 22]
#  [43 50]]

# 等价于
c = np.matmul(a, b)

8. 运算符优先级常见陷阱

8.1 位运算符优先级

位运算符的优先级低于比较运算符,这可能导致意外结果:

python
# 错误!
if flags & 0x01 == 0x01:  # 相当于 flags & (0x01 == 0x01)
    pass

# 正确
if (flags & 0x01) == 0x01:
    pass

8.2 幂运算符的结合性

幂运算符是右结合的:

python
print(2 ** 3 ** 2)  # 512,相当于 2 ** (3 ** 2)
print((2 ** 3) ** 2)  # 64

8.3 not 的优先级

not 的优先级低于比较运算符:

python
# 这两个是等价的
if not x == y:
    pass

if not (x == y):
    pass

# 如果想要 (not x) == y,必须加括号
if (not x) == y:
    pass

9. 成员运算符和身份运算符的性能

9.1 in 运算符的性能

不同数据结构的 in 运算符性能差异很大:

python
# 列表:O(n)
large_list = list(range(1000000))
print(999999 in large_list)  # 较慢

# 集合:O(1)
large_set = set(range(1000000))
print(999999 in large_set)   # 很快

# 字典:O(1)
large_dict = {i: i for i in range(1000000)}
print(999999 in large_dict)  # 很快

9.2 链式 isinstance 检查

使用元组可以简化多个类型检查:

python
# 传统写法
if isinstance(x, int) or isinstance(x, float) or isinstance(x, complex):
    print("x is a number")

# 更简洁的写法
if isinstance(x, (int, float, complex)):
    print("x is a number")

10. 参考资料

  1. Python 官方文档 - 表达式
  2. Python 官方文档 - 数据模型
  3. Python 运算符优先级

  1. 幂运算符 ** 绑定的紧密程度低于在其右侧的算术或按位一元运算符,也就是说 2**-10.5↩︎