推理基础设施 · Python5.5 常用魔术方法
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

💡 思路提示

点开看提示
  1. __getitem__ 让对象支持 obj[i] 索引
  2. __contains__ 让对象支持 x in obj
  3. __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 bb[1:3]),因为 Python 会“按索引一个个取”。

推理框架里 TokenizerBatchEmbedding 这些类通常都会实现 __len____getitem__,用起来和 list 一样自然。