5 道练习题·预计 35 分钟·做对一题解锁下一段
在 Python 中,所有以双下划线 __ 包起来的方法,都统称为 魔法方法(Magic Methods),也叫 魔术方法 / dunder 方法(dunder = double underscore)。
最常见的就是我们在上一章见过的 __init__。它在创建对象时自动被调用——你从来没有手动写过 obj.__init__(...),但它就是会跑。
魔法方法的能力远不止 __init__。它能让你自定义 Python 内置语法对你的对象的行为,比如:
| 写法 | 背后调用的魔法方法 |
|---|---|
print(obj) / str(obj) | __str__ |
obj1 == obj2 | __eq__ |
len(obj) | __len__ |
obj[0] | __getitem__ |
obj1 + obj2 | __add__ |
一句话:魔法方法 = 把你自己定义的类,接入 Python 内置语法。
任意一个类(哪怕一个空类)都已经从 object 继承了一堆魔法方法。用 dir() 可以查看:
class User:
pass
print(dir(User()))输出(截取一部分):
['__class__', '__delattr__', '__dict__', '__dir__', '__eq__', '__format__',
'__getattribute__', '__hash__', '__init__', '__lt__', '__new__', '__repr__',
'__setattr__', '__str__', ...]
可以看到,魔法方法非常多。本节我们挑最常用的几个学透——__str__ / __repr__、__eq__、__len__ / __getitem__、__add__。学完这几个,你写出的类就有了「Python 风味」。
__str__ 与 __repr__:让 print 输出友好先看一个问题。我们写一个最普通的 Book 类:
class Book:
def __init__(self, title):
self.title = title
b = Book('Python 入门')
print(b)输出是什么?
<__main__.Book object at 0x10a9f3d50>
一串 ✗ 的乱码。这是因为默认情况下,print(obj) 会调用 object 的 __str__,它只会告诉你「这是一个 Book 对象,地址是 0x...」——对人类来说毫无信息量。
__str__:给「人」看的字符串我们来重写它:
class Book:
def __init__(self, title):
self.title = title
def __str__(self):
return f'《{self.title}》'
b = Book('Python 入门')
print(b) # 《Python 入门》
print(str(b)) # 《Python 入门》__str__ 必须返回一个字符串。print(obj) 和 str(obj) 都会调用它。
__repr__:给「程序员」看的字符串__repr__ 也是返回字符串,但用途不同:它通常是面向开发者的、最好能复现这个对象的写法。
最典型的场景是:在交互式终端里直接敲变量名,或者把对象放进 list 后 print:
class Book:
def __init__(self, title):
self.title = title
def __str__(self):
return f'《{self.title}》'
def __repr__(self):
return f"Book(title={self.title!r})"
b = Book('Python 入门')
print(b) # 《Python 入门》 ← 走 __str__
print([b]) # [Book(title='Python 入门')] ← 容器里走 __repr__注意:
__repr__、没定义 __str__,那 print(obj) 会回退到 __repr____str__ 时,[obj] 仍然显示默认的乱码经验法则:至少先把
__repr__写了。再考虑要不要加更友好的__str__。
请定义类 Book:
__init__ 接收 title,保存到 self.title__str__ 返回字符串 f'《{self.title}》'然后实例化 Book('Python 入门') 赋给 b,并 print(b)。
输出应该是:
《Python 入门》