Python 运算符重载
运算符重载通过魔术方法实现,使自定义类支持 Python 原生运算符。
算术运算符
加法 add
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 __radd__(self, other):
return self.__add__(other)
def __iadd__(self, other):
self.x += other.x
self.y += other.y
return self
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6) (__add__)
print(v1 + v2) # 同上
v1 += v2
print(v1) # Vector(4, 6) (__iadd__,原地修改)
减法 sub
Python
class Money:
def __init__(self, amount):
self.amount = amount
def __sub__(self, other):
return Money(self.amount - other.amount)
def __str__(self):
return f"¥{self.amount}"
m1 = Money(100)
m2 = Money(30)
print(m1 - m2) # ¥70
其他算术运算符
Python
class Number:
def __init__(self, value):
self.value = value
def __add__(self, other):
return Number(self.value + other.value)
def __sub__(self, other):
return Number(self.value - other.value)
def __mul__(self, other):
return Number(self.value * other.value)
def __truediv__(self, other):
return Number(self.value / other.value)
def __floordiv__(self, other):
return Number(self.value // other.value)
def __mod__(self, other):
return Number(self.value % other.value)
def __pow__(self, other):
return Number(self.value ** other.value)
def __str__(self):
return str(self.value)
a = Number(10)
b = Number(3)
print(a + b) # 13
print(a - b) # 7
print(a * b) # 30
print(a / b) # 3.333...
print(a // b) # 3
print(a % b) # 1
print(a ** b) # 1000
| 方法 | 运算符 | 说明 |
|---|---|---|
__add__ | + | 加法 |
__sub__ | - | 减法 |
__mul__ | * | 乘法 |
__truediv__ | / | 除法 |
__floordiv__ | // | 整除 |
__mod__ | % | 取模 |
__pow__ | ** | 幂运算 |
反向运算符
当左操作数不支持运算时,调用右操作数的反向方法:
Python
class MyNum:
def __init__(self, val):
self.val = val
def __add__(self, other):
if isinstance(other, MyNum):
return MyNum(self.val + other.val)
return NotImplemented
def __radd__(self, other):
# 当左侧不支持加法时调用
return MyNum(other + self.val)
n = MyNum(10)
print(5 + n) # MyNum(15)(调用 __radd__)
print(n + 5) # 返回 NotImplemented,然后调用 int.__radd__
| 正向方法 | 反向方法 | 触发条件 |
|---|---|---|
__add__ | __radd__ | other + self |
__sub__ | __rsub__ | other - self |
__mul__ | __rmul__ | other * self |
__truediv__ | __rtruediv__ | other / self |
增量运算符
Python
class Counter:
def __init__(self, value):
self.value = value
def __iadd__(self, other):
self.value += other
return self # 必须返回 self
def __isub__(self, other):
self.value -= other
return self
c = Counter(10)
c += 5 # 原地加法 (__iadd__)
print(c.value) # 15
c -= 3
print(c.value) # 12
| 方法 | 运算符 |
|---|---|
__iadd__ | += |
__isub__ | -= |
__imul__ | *= |
__itruediv__ | /= |
比较运算符
Python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
return self.age == other.age
def __ne__(self, other):
return self.age != other.age
def __lt__(self, other):
return self.age < other.age
def __le__(self, other):
return self.age <= other.age
def __gt__(self, other):
return self.age > other.age
def __ge__(self, other):
return self.age >= other.age
p1 = Person("Alice", 25)
p2 = Person("Bob", 30)
p3 = Person("Carol", 25)
print(p1 == p3) # True
print(p1 < p2) # True
print(p2 > p1) # True
使用
functools.total_ordering可只实现__eq__和一个比较方法:
Python
from functools import total_ordering
@total_ordering
class Score:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return self.value == other.value
def __lt__(self, other):
return self.value < other.value
s1 = Score(80)
s2 = Score(90)
print(s1 < s2) # True
print(s1 <= s2) # True(自动生成)
print(s1 > s2) # False(自动生成)
位运算符
Python
class Flags:
def __init__(self, bits):
self.bits = bits
def __and__(self, other):
return Flags(self.bits & other.bits)
def __or__(self, other):
return Flags(self.bits | other.bits)
def __xor__(self, other):
return Flags(self.bits ^ other.bits)
def __invert__(self):
return Flags(~self.bits)
def __lshift__(self, other):
return Flags(self.bits << other)
def __rshift__(self, other):
return Flags(self.bits >> other)
f1 = Flags(0b1010)
f2 = Flags(0b1100)
print(bin(f1 & f2.bits)) # 0b1000
print(bin(f1 | f2.bits)) # 0b1110
print(bin(f1 ^ f2.bits)) # 0b0110
print(bin(~f1.bits)) # -0b1011
| 方法 | 运算符 |
|---|---|
__and__ | & |
__or__ | ` |
__xor__ | ^ |
__invert__ | ~ |
__lshift__ | << |
__rshift__ | >> |
一元运算符
Python
class Balance:
def __init__(self, amount):
self.amount = amount
def __neg__(self):
return Balance(-self.amount)
def __pos__(self):
return Balance(self.amount)
def __abs__(self):
return Balance(abs(self.amount))
def __str__(self):
return f"¥{self.amount}"
b = Balance(100)
print(-b) # ¥-100
print(+b) # ¥100
print(abs(b)) # ¥100
| 方法 | 运算符 |
|---|---|
__neg__ | -obj |
__pos__ | +obj |
__abs__ | abs(obj) |
完整示例:矩阵类
Python
class Matrix:
def __init__(self, data):
self.data = data
self.rows = len(data)
self.cols = len(data[0]) if data else 0
def __add__(self, other):
if self.rows != other.rows or self.cols != other.cols:
raise ValueError("矩阵维度不匹配")
result = [
[self.data[i][j] + other.data[i][j]
for j in range(self.cols)]
for i in range(self.rows)
]
return Matrix(result)
def __mul__(self, other):
if isinstance(other, Matrix):
if self.cols != other.rows:
raise ValueError("无法相乘")
result = [
[sum(self.data[i][k] * other.data[k][j]
for k in range(self.cols))
for j in range(other.cols)]
for i in range(self.rows)
]
return Matrix(result)
else:
# 数乘
return Matrix([[x * other for x in row] for row in self.data])
def __rmul__(self, other):
return self.__mul__(other)
def __eq__(self, other):
return self.data == other.data
def __str__(self):
return '\n'.join([' '.join(map(str, row)) for row in self.data])
m1 = Matrix([[1, 2], [3, 4]])
m2 = Matrix([[5, 6], [7, 8]])
print(m1 + m2)
# 6 8
# 10 12
print(m1 * m2)
# 19 22
# 43 50
print(2 * m1)
# 2 4
# 6 8
要点总结
| 类别 | 常用方法 |
|---|---|
| 算术 | __add__、__sub__、__mul__、__truediv__ |
| 反向 | __radd__、__rsub__、__rmul__ |
| 增量 | __iadd__、__isub__ |
| 比较 | __eq__、__lt__、__gt__ |
| 位运算 | __and__、__or__、__xor__ |
| 一元 | __neg__、__pos__、__abs__ |
返回
NotImplemented会让 Python 尝试反向方法,适合处理混合类型运算。
D:\git2\jwdev\articles\PYTHON\进阶\面向对象编程\运算符重载.md
📝 发现内容有误?点击此处直接编辑