Python __sub__ 方法
最后修改于 2025 年 4 月 8 日
本综合指南将探讨 Python 的 __sub__
方法,该特殊方法实现了减法运算 (-)。我们将涵盖基本用法、向量数学、自定义行为和实际示例。
基本定义
__sub__
方法被调用来实现减法运算符 (-)。当你写 x - y
时,Python 会尝试调用 x.__sub__(y)
。
主要特点:它必须接受两个参数(self 和 other),返回减法结果,并且可以被重写以自定义行为。它适用于内置类型和自定义类型。
基本 __sub__ 实现
这是一个简单的类,实现了 __sub__
以演示同类型对象之间的基本减法行为。
class Number: def __init__(self, value): self.value = value def __sub__(self, other): if isinstance(other, Number): return Number(self.value - other.value) return NotImplemented a = Number(10) b = Number(3) result = a - b print(result.value) # Output: 7
此示例展示了如何实现 Number 对象之间的基本减法。__sub__
方法会检查另一个操作数是否也是 Number。
返回 NotImplemented
会告诉 Python 尝试执行反向运算(__rsub__
),如果可用的话。这可以保持运算符的灵活性。
向量减法
__sub__
方法常用于数学运算,如向量减法,即我们减去相应的分量。
class Vector: def __init__(self, x, y): self.x = x self.y = y def __sub__(self, other): if isinstance(other, Vector): return Vector(self.x - other.x, self.y - other.y) return NotImplemented def __repr__(self): return f"Vector({self.x}, {self.y})" v1 = Vector(5, 7) v2 = Vector(3, 2) result = v1 - v2 print(result) # Output: Vector(2, 5)
此 Vector 类实现了逐分量减法。__sub__
方法创建并返回一个具有减去分量的新 Vector。
__repr__
方法提供了向量的可读字符串表示形式,使调试和输出更加清晰。
减去不同类型
__sub__
可以通过检查另一个操作数的类型并实现适当的行为来处理不同类型之间的运算。
class Currency: def __init__(self, amount, currency_code): self.amount = amount self.currency_code = currency_code def __sub__(self, other): if isinstance(other, Currency): if self.currency_code != other.currency_code: raise ValueError("Cannot subtract different currencies") return Currency(self.amount - other.amount, self.currency_code) elif isinstance(other, (int, float)): return Currency(self.amount - other, self.currency_code) return NotImplemented def __repr__(self): return f"{self.amount} {self.currency_code}" usd1 = Currency(100, "USD") usd2 = Currency(30, "USD") print(usd1 - usd2) # 70 USD print(usd1 - 15) # 85 USD
此 Currency 类允许减去同类型 Currency 对象,并且还支持直接从金额中减去数字。
该方法包含类型检查和货币验证,以确保只执行有意义的运算。这使得该类更加健壮。
使用 __rsub__ 进行反向减法
当左操作数不支持与右操作数进行减法时,Python 会尝试使用 __rsub__
执行反向运算。
class Temperature: def __init__(self, value): self.value = value def __sub__(self, other): if isinstance(other, Temperature): return Temperature(self.value - other.value) return NotImplemented def __rsub__(self, other): if isinstance(other, (int, float)): return Temperature(other - self.value) return NotImplemented def __repr__(self): return f"{self.value}°C" temp = Temperature(10) result1 = temp - Temperature(3) # Uses __sub__ result2 = 20 - temp # Uses __rsub__ print(result1) # 7°C print(result2) # 10°C
此示例同时展示了正常减法和反向减法。当 Python 遇到 20 - temp
时,它首先尝试 int.__sub__
,但失败了。
然后它尝试 temp.__rsub__(20)
,这是成功的。这使得该类在与内置类型一起使用时更加灵活。
原地减法 __isub__
__isub__
方法实现了原地减法 (-=),它会修改对象而不是创建新对象。
class Account: def __init__(self, balance): self.balance = balance def __sub__(self, other): if isinstance(other, (int, float)): return Account(self.balance - other) return NotImplemented def __isub__(self, other): if isinstance(other, (int, float)): self.balance -= other return self return NotImplemented def __repr__(self): return f"Account(balance={self.balance})" acc = Account(100) acc -= 30 # Uses __isub__ print(acc) # Account(balance=70)
__isub__
方法直接修改对象的状态并返回 self。当你不需要新对象时,这比 __sub__
更有效。
对于可变对象,实现 __isub__
可以通过避免不必要的对象创建来提供更好的性能。
最佳实践
- 类型检查:始终在 __sub__ 中验证操作数类型
- 返回 NotImplemented:对于不支持的操作
- 实现 __rsub__:用于反向运算支持
- 考虑 __isub__:用于高效的原地运算
- 保持一致性:确保减法遵循数学规则
资料来源
作者
列出所有 Python 教程。