运算符重载
本课属于 Coddy Python 学习旅程的“面向对象编程”单元。第 34 课,共 64 课。
通过实现特殊的魔法方法,运算符重载可以让你的类使用 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 __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
def __str__(self):
return f"Vector({self.x}, {self.y})"__add__ 方法定义了使用 + 运算符时会发生什么:
v1 = Vector(2, 3)
v2 = Vector(5, 7)
result = v1 + v2 # 调用 v1.__add__(v2)
print(result)__mul__ 方法定义了使用 * 运算符时会发生什么:
v1 = Vector(2, 3)
scaled = v1 * 3 # 调用 v1.__mul__(3)
print(scaled)输出:
Vector(7, 10)
Vector(6, 9)添加比较运算符:
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 __eq__(self, other):
return self.x == other.x and self.y == other.y
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(1, 1)
print(v1 == v2) # True:调用 v1.__eq__(v2)
print(v1 == v3) # False要点:运算符重载使用 __add__ (+)、__sub__ (-)、__mul__ (*) 和 __eq__ (==) 等魔术方法,来定义运算符如何作用于你的对象。这样,你的类就能自然地使用 Python 内置的运算符。
挑战
中等在这个挑战中,你将实现一个 Money 类,用于表示货币金额,并支持可靠的运算符重载。我们会使用全面的测试套件对你的实现进行彻底测试。
money.py:这是你唯一需要编辑的文件。其中包含类定义,以及指导你完成实现的 TODO 注释。driver.py:其中包含大量用于验证你实现的测试场景(不要修改)。
请实现 Money 类,并支持以下功能:
- 构造函数,接收
amount(浮点数)和currency(字符串) - 对货币相同的 Money 对象进行加法运算(
+) - 将金额乘以一个数字进行缩放(
*) - 比较 Money 对象是否相等(
==) - 以 “X.XX CUR” 格式表示字符串
亲手试试
from money import Money
# 测试用例处理程序
test_case = input()
def test_basic_functionality():
# 测试初始化和字符串表示
m1 = Money(10.0, "USD")
assert str(m1) == "10.00 USD", f"__str__ method failed, got {str(m1)}"
# 测试加法
m2 = Money(20.0, "USD")
m3 = m1 + m2
assert str(m3) == "30.00 USD", f"Addition failed, got {str(m3)}"
# 测试不同货币之间的加法
m4 = Money(20.0, "EUR")
try:
m5 = m1 + m4
assert False, "Adding different currencies should raise an error"
except ValueError as e:
assert str(e) == "Cannot add different currencies", f"Wrong error message: {str(e)}"
# 测试乘法
m6 = m1 * 3
assert str(m6) == "30.00 USD", f"Multiplication failed, got {str(m6)}"
# 测试相等性
assert m1 == Money(10.0, "USD"), "Equality test failed"
assert m1 != m2, "Inequality test failed"
print("All basic functionality tests passed!")
def test_zero_values():
# 测试金额为零的情况
m1 = Money(0.0, "USD")
assert str(m1) == "0.00 USD", f"Zero amount string representation failed, got {str(m1)}"
# 测试与零相加
m2 = Money(10.0, "USD")
m3 = m1 + m2
assert str(m3) == "10.00 USD", f"Addition with zero failed, got {str(m3)}"
# 测试乘以零
m4 = m2 * 0
assert str(m4) == "0.00 USD", f"Multiplication by zero failed, got {str(m4)}"
# 测试金额为零时的相等性
assert m1 == Money(0.0, "USD"), "Equality with zero amount failed"
assert m1 != m2, "Inequality with zero amount failed"
print("All zero value tests passed!")
def test_negative_values():
# 测试金额为负数的情况
m1 = Money(-10.0, "USD")
assert str(m1) == "-10.00 USD", f"Negative amount string representation failed, got {str(m1)}"
# 测试负数金额的加法
m2 = Money(20.0, "USD")
m3 = m1 + m2
assert str(m3) == "10.00 USD", f"Addition with negative amount failed, got {str(m3)}"
m4 = Money(-5.0, "USD")
m5 = m1 + m4
assert str(m5) == "-15.00 USD", f"Addition of two negative amounts failed, got {str(m5)}"
# 测试乘以负数标量
m6 = m2 * -2
assert str(m6) == "-40.00 USD", f"Multiplication by negative scalar failed, got {str(m6)}"
# 测试负金额的相等性
assert m1 == Money(-10.0, "USD"), "Equality with negative amount failed"
assert m1 != m2, "Inequality with negative amount failed"
print("All negative value tests passed!")
def test_large_values():
# 测试非常大的金额
m1 = Money(1000000.0, "USD")
assert str(m1) == "1000000.00 USD", f"Large amount string representation failed, got {str(m1)}"
# 测试大金额相加
m2 = Money(2000000.0, "USD")
m3 = m1 + m2
assert str(m3) == "3000000.00 USD", f"Addition with large amounts failed, got {str(m3)}"
# 测试乘以较大的标量
m4 = m1 * 1000
assert str(m4) == "1000000000.00 USD", f"Multiplication with large scalar failed, got {str(m4)}"
print("All large value tests passed!")
def test_precision():
# 测试带小数的金额
m1 = Money(10.25, "USD")
assert str(m1) == "10.25 USD", f"Fractional amount string representation failed, got {str(m1)}"
m2 = Money(10.2, "USD")
assert str(m2) == "10.20 USD", f"Two decimal place formatting failed, got {str(m2)}"
# 测试带小数的金额相加
m3 = Money(0.75, "USD")
m4 = m1 + m3
assert str(m4) == "11.00 USD", f"Addition with fractional amounts failed, got {str(m4)}"
# 测试乘以小数标量
m5 = m1 * 0.4
assert str(m5) == "4.10 USD", f"Multiplication with fractional scalar failed, got {str(m5)}"
print("All precision tests passed!")
def test_type_validation():
try:
# 这些操作应该不会出错
m1 = Money(10.0, "USD")
m2 = m1 * 2
m3 = m1 * 2.5
# 测试与不同数据类型比较是否相等
assert (m1 == "10.00 USD") == False, "Equality with string should return False"
assert (m1 == 10.0) == False, "Equality with number should return False"
print("All type validation tests passed!")
except Exception as e:
print(f"Type validation test failed: {e}")
def test_currency_case_sensitivity():
# 测试货币代码是否区分大小写
m1 = Money(10.0, "USD")
m2 = Money(10.0, "usd")
# 货币代码应该区分大小写
assert m1 != m2, "Currency comparison should be case-sensitive"
# 添加大小写不同的货币应失败
try:
m3 = m1 + m2
assert False, "Adding different currency cases should raise an error"
except ValueError as e:
assert str(e) == "Cannot add different currencies", f"Wrong error message: {str(e)}"
print("All currency case sensitivity tests passed!")
def test_performance():
# 创建多个 Money 对象并执行运算
base = Money(1.0, "USD")
result = base
# 执行 1000 次加法运算
for i in range(1000):
result = result + Money(1.0, "USD")
assert str(result) == "1001.00 USD", f"Performance test addition failed, got {str(result)}"
# 执行 10 次乘法运算
result = base
for i in range(10):
result = result * 2
assert str(result) == "1024.00 USD", f"Performance test multiplication failed, got {str(result)}"
print("All performance tests passed!")
# 根据输入运行相应的测试
if test_case == "basic_test":
test_basic_functionality()
elif test_case == "zero_values":
test_zero_values()
elif test_case == "negative_values":
test_negative_values()
elif test_case == "large_values":
test_large_values()
elif test_case == "precision":
test_precision()
elif test_case == "type_validation":
test_type_validation()
elif test_case == "currency_case":
test_currency_case_sensitivity()
elif test_case == "performance":
test_performance()
else:
print(f"Unknown test case: {test_case}")这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Python 在线编译器