第 36 课 · 阶段六 · 面向对象

魔术方法

以双下划线包裹的方法叫“魔术方法”,它们在特定时机被自动调用。这一课掌握最常用的几个,让对象更智能、更 Pythonic。

第 36 课阶段六 · 面向对象难度:进阶建议时长:35 分钟关键词:__str__ · __eq__ · __add__

🎯 学完本课你将掌握

  • 理解魔术方法的概念
  • 掌握 __str__/__repr__/__eq__/__lt__ 等
  • 会用魔术方法做对象间的运算与比较

一、什么是魔术方法

形如 __xxx__ 的方法会在特定场景自动触发,比如打印对象时自动调用 __str__。它们是 Python 对象的内置协议。

二、__str__ 与 __repr__:让对象“看得懂”

str repr.py
1class Point:
2 def __init__(self, x, y):
3 self.x, self.y = x, y
4
5 def __str__(self):
6 return f"({self.x}, {self.y})" # 打印时显示
7
8p = Point(3, 5)
9print(p) # (3, 5) 而不是 <__main__.Point object at 0x...>

三、__eq__:对象相等比较

eq 用法.py
1class Point:
2 def __init__(self, x, y):
3 self.x, self.y = x, y
4
5 def __eq__(self, other):
6 return self.x == other.x and self.y == other.y
7
8print(Point(1, 2) == Point(1, 2)) # True(默认会比较地址)
9print(Point(1, 2) == Point(3, 4)) # False

四、__lt__ 等比较方法:让对象能排序

比较排序.py
1class Student:
2 def __init__(self, name, score):
3 self.name, self.score = name, score
4
5 def __lt__(self, other): # 定义“小于”规则
6 return self.score < other.score
7
8 def __str__(self):
9 return f"{self.name}:{self.score}"
10
11students = [Student("小明", 92), Student("小红", 78), Student("小刚", 88)]
12for s in sorted(students): # 按分数升序
13 print(s)

五、__add__:让对象支持 + 运算

add 用法.py
1class Vector:
2 def __init__(self, x, y):
3 self.x, self.y = x, y
4
5 def __add__(self, other):
6 return Vector(self.x + other.x, self.y + other.y)
7
8 def __str__(self):
9 return f"({self.x}, {self.y})"
10
11v = Vector(1, 2) + Vector(3, 4)
12print(v) # (4, 6)

六、__len__ 与 __getitem__:像列表一样用

len getitem.py
1class Scores:
2 def __init__(self, items):
3 self.items = items
4 def __len__(self):
5 return len(self.items)
6 def __getitem__(self, i):
7 return self.items[i]
8
9s = Scores([88, 92, 76])
10print(len(s)) # 3
11print(s[1]) # 92 支持下标访问
12for x in s: # 还支持遍历
13 print(x, end=" ")

七、常用魔术方法速查表

方法触发时机
__init__(self, ...)创建对象时
__str__/__repr__print 或字符串化时
__eq__/__lt__/__gt__比较 == 与 < > 时
__add__/__sub__+ 与 - 运算时
__len__len() 时
__getitem__下标访问 obj[i] 时

八、常见错误与解决

常见错误与解决

错误现象原因 / 解决方法
比较对象总是不相等没定义 __eq__,默认比较内存地址;按属性比较就实现 __eq__。
sorted 排序报错没定义 __lt__ 且没传 key;实现 __lt__ 或改用 key=lambda。
打印对象是 <object at 0x...>实现了 __str__ 或 __repr__ 就会显示友好内容。
✍️ 小练习
给 Student 类实现 __lt__(按分数)、__eq__(同名同分相等)、__str__;创建 4 个学生排序打印。
📌 本节小结
魔术方法让对象参与 Python 的“原生操作”:__str__ 打印、__eq__ 比较、__lt__ 排序、__add__ 运算、__len__/__getitem__ 变可迭代。它们是面向对象的高级语法糖。