Python __add__ 方法
最后修改于 2025 年 4 月 8 日
本综合指南探讨了 Python 的 __add__
方法,该方法是实现加法运算符 (+) 的特殊方法。我们将介绍基本用法、运算符重载、类型处理和实际示例。
基本定义
当对象使用 + 运算符时,会调用 __add__
方法。它定义了当类的实例与其他对象相加时应如何表现。这是 Python 运算符重载机制的一部分。
主要特点:它接受 self
和另一个操作数作为参数,应返回加法的结果,并且可以为不支持的操作引发 NotImplemented
。它支持自定义加法行为。
基本的 __add__ 实现
这是一个简单的实现,展示了 __add__
如何与自定义类一起工作。此示例演示了两个对象之间的基本加法。
class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): if isinstance(other, Vector): return Vector(self.x + other.x, self.y + other.y) return NotImplemented v1 = Vector(2, 4) v2 = Vector(5, 1) v3 = v1 + v2 print(f"Result: ({v3.x}, {v3.y})") # Output: (7, 5)
这个 Vector 类通过 __add__
实现向量加法。当两个 Vector 实例相加时,它返回一个包含求和分量的新 Vector。
NotImplemented
返回值表示不支持的操作。然后,Python 将尝试另一个操作数的 __radd__
方法(如果可用)。
处理不同的类型
__add__
可以通过检查 other
参数类型并实现适当的行为来处理不同类型的操作。
class Currency: def __init__(self, amount, currency_code): self.amount = amount self.code = currency_code def __add__(self, other): if isinstance(other, Currency): if self.code == other.code: return Currency(self.amount + other.amount, self.code) raise ValueError("Cannot add different currencies") elif isinstance(other, (int, float)): return Currency(self.amount + other, self.code) return NotImplemented usd1 = Currency(50, "USD") usd2 = Currency(75, "USD") print((usd1 + usd2).amount) # 125 try: eur = Currency(100, "EUR") usd1 + eur # Raises ValueError except ValueError as e: print(e)
这个 Currency 类允许与其他 Currency 对象(仅限相同货币)以及数字相加。它演示了类型检查和不同的行为。
该示例展示了如何实现业务规则(相同货币要求)并支持多种操作数类型,同时保持类型安全。
实现 __radd__ 以进行右加法
当左操作数不支持加法时,Python 会在右操作数上调用 __radd__
。同时实现两者可以使操作具有交换性。
class Temperature: def __init__(self, celsius): self.celsius = celsius def __add__(self, other): if isinstance(other, (int, float)): return Temperature(self.celsius + other) return NotImplemented def __radd__(self, other): return self.__add__(other) t1 = Temperature(20) t2 = 5 + t1 # Uses __radd__ t3 = t1 + 10 # Uses __add__ print(t2.celsius) # 25 print(t3.celsius) # 30
此 Temperature 类支持与任何一侧的数字相加。__radd__
方法委托给 __add__
以获得一致的行为。
如果没有 __radd__
,5 + t1
将会失败,因为整数不知道如何添加 Temperature 对象。这使得操作具有交换性。
使用 __iadd__ 进行原地加法
__iadd__
方法实现 += 运算符以进行原地加法。为了提高效率,它应该修改并返回自身(如果可能)。
class ShoppingCart: def __init__(self): self.items = [] def __add__(self, other): new_cart = ShoppingCart() new_cart.items = self.items.copy() if isinstance(other, ShoppingCart): new_cart.items.extend(other.items) elif isinstance(other, list): new_cart.items.extend(other) else: return NotImplemented return new_cart def __iadd__(self, other): if isinstance(other, ShoppingCart): self.items.extend(other.items) elif isinstance(other, list): self.items.extend(other) else: return NotImplemented return self cart = ShoppingCart() cart += ["apple", "banana"] # Uses __iadd__ cart = cart + ["orange"] # Uses __add__ print(cart.items) # ['apple', 'banana', 'orange']
这个 ShoppingCart 展示了 __add__
(创建新对象)和 __iadd__
(修改现有对象)之间的区别。 += 在可用时使用 __iadd__
。
__iadd__
应该返回 self 以匹配 Python 的原地操作语义。这允许链式操作并保持预期行为。
将自定义对象添加到内置类型
通过在该方法中实现适当的类型处理,__add__
可以支持将自定义对象添加到 Python 内置类型。
class Measurement: def __init__(self, value, unit): self.value = value self.unit = unit def __add__(self, other): if isinstance(other, Measurement): if self.unit == other.unit: return Measurement(self.value + other.value, self.unit) raise ValueError("Units must match") elif isinstance(other, (int, float)): return Measurement(self.value + other, self.unit) return NotImplemented def __radd__(self, other): return self.__add__(other) def __str__(self): return f"{self.value} {self.unit}" m1 = Measurement(5, "kg") m2 = Measurement(3, "kg") print(m1 + m2) # 8 kg print(m1 + 2.5) # 7.5 kg print(10 + m2) # 13 kg
这个 Measurement 类支持与其他 Measurements(相同单位)以及数字相加。__radd__
启用了 number + Measurement 语法。
该示例展示了如何在提供自定义和内置类型灵活加法功能的同时,保持单位一致性。
最佳实践
- 类型检查: 始终在 __add__ 中验证操作数类型
- 实现 __radd__: 尽可能使操作具有交换性
- 返回 NotImplemented: 对于不支持的操作
- 考虑 __iadd__: 为了高效的原地操作
- 保持一致性: 确保 + 和 += 的行为符合逻辑
资料来源
作者
列出所有 Python 教程。