05
基础面向对象 · 5 / 5
5.5 常用魔术方法
💡 推理里把 Batch 当 list 用、把 Config 当 dict 用,全靠魔术方法
5.5 常用魔术方法
魔术方法 = 双下划线方法,让你的对象支持 Python 内置操作
| 方法 | 触发场景 |
|---|---|
__init__ |
创建实例 |
__repr__ |
在 REPL / print 时显示 |
__str__ |
str(obj) / print |
__len__ |
len(obj) |
__getitem__ |
obj[i] |
__contains__ |
x in obj |
__iter__ |
for x in obj |
__eq__ |
obj1 == obj2 |
__enter__ / __exit__ |
with 语句 |
示范
class FakeBatch:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
def __getitem__(self, i):
return self.items[i]
def __repr__(self):
return f"FakeBatch({self.items!r})"
b = FakeBatch([1, 2, 3])
print(len(b), b[0], b) # 3 1 FakeBatch([1, 2, 3])
class Request:
def __init__(self, prompt, n):
self.prompt = prompt
self.n = n
def __repr__(self):
return f"Request(prompt={self.prompt!r}, n={self.n})"
r = Request("hi", 128)
print(r) # Request(prompt='hi', n=128)
print([r, r]) # 列表里也会显示 repr
✍️ 练习
定义类 Batch,让它用起来像 list:
__init__(self, items):存self.items = list(items)__len__(self):返回len(self.items)__getitem__(self, i):返回self.items[i]__repr__(self):返回f"Batch({self.items!r})"__contains__(self, item):return item in self.items
测试:
b = Batch([1, 2, 3, 4])
print(len(b), b[0], b, 2 in b, 99 in b)
# 期望:4 1 Batch([1, 2, 3, 4]) True False
💡 思路提示
点开看提示
__getitem__让对象支持obj[i]索引__contains__让对象支持x in obj__repr__在 print 时被调用
✅ 参考解法
写不出来再打开
class Batch:
def __init__(self, items):
self.items = list(items)
def __len__(self):
return len(self.items)
def __getitem__(self, i):
return self.items[i]
def __repr__(self):
return f"Batch({self.items!r})"
def __contains__(self, item):
return item in self.items
b = Batch([1, 2, 3, 4])
print(len(b), b[0], b, 2 in b, 99 in b)
🔍 进阶思考
实现了 __getitem__ 后,你的对象就自动支持迭代和切片(for x in b、b[1:3]),因为 Python 会“按索引一个个取”。
推理框架里 Tokenizer、Batch、Embedding 这些类通常都会实现 __len__ 和 __getitem__,用起来和 list 一样自然。