第 36 课 · 阶段六 · 面向对象
魔术方法
以双下划线包裹的方法叫“魔术方法”,它们在特定时机被自动调用。这一课掌握最常用的几个,让对象更智能、更 Pythonic。
🎯 学完本课你将掌握
- 理解魔术方法的概念
- 掌握 __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, y45 def __str__(self):6 return f"({self.x}, {self.y})" # 打印时显示78p = 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, y45 def __eq__(self, other):6 return self.x == other.x and self.y == other.y78print(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, score45 def __lt__(self, other): # 定义“小于”规则6 return self.score < other.score78 def __str__(self):9 return f"{self.name}:{self.score}"1011students = [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, y45 def __add__(self, other):6 return Vector(self.x + other.x, self.y + other.y)78 def __str__(self):9 return f"({self.x}, {self.y})"1011v = 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 = items4 def __len__(self):5 return len(self.items)6 def __getitem__(self, i):7 return self.items[i]89s = Scores([88, 92, 76])10print(len(s)) # 311print(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__ 变可迭代。它们是面向对象的高级语法糖。