魔法方法
本节目标
学完这一节,你会知道:
- 什么是魔法方法
__str__和__repr__有什么用- 如何让对象支持
len() - 如何让对象支持
+运算 - 如何让自定义类用起来更像 Python 内置类型
魔法方法不是魔法,它只是 Python 约定的一组特殊方法名。
先跑一个例子
新建文件 magic_demo.py,写入:
class Book:
def __init__(self, title, price):
self.title = title
self.price = price
def __str__(self):
return f"《{self.title}》售价 {self.price} 元"
book = Book("Python 入门", 59)
print(book)
运行:
python3 magic_demo.py
你会看到:
《Python 入门》售价 59 元
如果没有 __str__(),打印对象时会显示一串不友好的默认信息。
什么是魔法方法?
魔法方法是前后都有双下划线的方法,比如:
__init__
__str__
__len__
__add__
这些方法会在特定语法中被 Python 自动调用。
例如:
- 创建对象时调用
__init__ print(obj)时调用__str__len(obj)时调用__len__obj1 + obj2时调用__add__
str:给用户看的字符串
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def __str__(self):
return f"{self.name}:{self.score} 分"
student = Student("小明", 85)
print(student)
输出:
小明:85 分
__str__() 必须返回字符串。
repr:给开发者看的字符串
__repr__() 通常用于调试,尽量返回能看清对象内容的字符串。
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def __repr__(self):
return f"Student(name={self.name!r}, score={self.score!r})"
student = Student("小明", 85)
print(repr(student))
!r 会使用更适合调试的表示方式,比如字符串会带引号。
如果只写一个,初学时先写 __str__() 就够了。
len:支持 len()
class Team:
def __init__(self, name):
self.name = name
self.members = []
def add_member(self, member):
self.members.append(member)
def __len__(self):
return len(self.members)
team = Team("Python 学习小组")
team.add_member("小明")
team.add_member("小红")
print(len(team))
len(team) 会自动调用 team.__len__()。
add:支持加法
class Money:
def __init__(self, amount):
self.amount = amount
def __add__(self, other):
return Money(self.amount + other.amount)
def __str__(self):
return f"{self.amount} 元"
a = Money(10)
b = Money(20)
print(a + b)
输出:
30 元
a + b 会自动调用 a.__add__(b)。
eq:支持相等判断
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __eq__(self, other):
return self.name == other.name and self.price == other.price
p1 = Product("苹果", 3.5)
p2 = Product("苹果", 3.5)
print(p1 == p2)
如果不写 __eq__(),两个不同对象通常不会因为内容相同就相等。
逐行拆解
再看开头的例子:
def __str__(self):
return f"《{self.title}》售价 {self.price} 元"
定义对象被转换成字符串时的显示方式。
print(book)
Python 发现要打印 book,就自动调用 book.__str__()。
自己改一改
把 magic_demo.py 改成:
class Course:
def __init__(self, title, lessons):
self.title = title
self.lessons = lessons
def __str__(self):
return f"{self.title},共 {self.lessons} 节"
def __len__(self):
return self.lessons
course = Course("Python 入门", 25)
print(course)
print(len(course))
然后继续改:
- 增加
__repr__() - 创建两个课程对象
- 用
__eq__()判断两个课程标题是否相同
了解即可:让对象像列表
如果实现 __getitem__(),对象可以用索引访问。
class Playlist:
def __init__(self):
self.songs = []
def add(self, song):
self.songs.append(song)
def __len__(self):
return len(self.songs)
def __getitem__(self, index):
return self.songs[index]
playlist = Playlist()
playlist.add("歌曲 A")
playlist.add("歌曲 B")
print(len(playlist))
print(playlist[0])
这类方法以后写自定义容器时会用到。
常见魔法方法速查
| 方法 | 触发方式 |
|---|---|
__init__ |
创建对象 |
__str__ |
print(obj)、str(obj) |
__repr__ |
repr(obj)、调试显示 |
__len__ |
len(obj) |
__add__ |
obj + other |
__eq__ |
obj == other |
__getitem__ |
obj[index] |
__contains__ |
item in obj |
__iter__ |
for item in obj |
不用一次背完。看到语法时,知道背后会调用对应方法就行。
常见错误
1. str 返回的不是字符串
错误写法:
def __str__(self):
return 123
__str__() 必须返回字符串。
2. 魔法方法名字写错
def _str_(self):
return "hello"
前后都要两个下划线:
def __str__(self):
return "hello"
3. add 没有返回新对象
如果 a + b 需要产生结果,__add__() 应该返回一个结果,而不是只打印。
4. 过度使用魔法方法
魔法方法应该让对象更自然,而不是让代码更难懂。只有当行为符合直觉时才使用。
小练习
练习 1:Book 显示
定义 Book 类,实现 __str__(),让 print(book) 输出书名和作者。
练习 2:购物车长度
定义 Cart 类,里面有商品列表,实现 __len__() 返回商品数量。
练习 3:金额相加
定义 Money 类,实现 __add__(),让两个金额对象可以相加。
参考答案
练习 1:
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __str__(self):
return f"《{self.title}》,作者:{self.author}"
练习 2:
class Cart:
def __init__(self):
self.items = []
def add(self, item):
self.items.append(item)
def __len__(self):
return len(self.items)
cart = Cart()
cart.add("苹果")
cart.add("牛奶")
print(len(cart))
练习 3:
class Money:
def __init__(self, amount):
self.amount = amount
def __add__(self, other):
return Money(self.amount + other.amount)
def __str__(self):
return f"{self.amount} 元"
print(Money(10) + Money(20))
小结
这一节你学会了:
- 魔法方法是 Python 自动调用的特殊方法
__str__()控制对象打印效果__repr__()更适合调试显示__len__()让对象支持len()__add__()、__eq__()可以让对象支持运算和比较
到这里,你已经走完了 Python 基础教程的主要路线。接下来可以把这些知识组合起来,做命令行工具、网页后端、爬虫或自动化脚本。
魔法方法不玄,只是 Python 早就约好了暗号
__str__、__len__、__add__ 这些名字看着像秘密咒语,其实是在告诉 Python:我的对象也想支持打印、求长度、相加。先让 Book、Cart、Money 跑起来,你会发现自定义对象也能变得很顺手。
还没有评论,来抢沙发吧!