第64集:魔术方法基础

学习目标

  • 理解魔术方法(特殊方法)的概念与作用
  • 掌握魔术方法的命名规则(__方法名__
  • 学会常用的对象生命周期魔术方法
  • 了解魔术方法如何让自定义类更好地融入 Python 生态
  • 初步具备使用魔术方法增强类功能的能力

1. 什么是魔术方法

魔术方法(Magic Methods / Special Methods)是 Python 中以双下划线 __ 包围的特殊方法,例如 __init____str____len__ 等。
它们在特定场景下会被 Python 自动调用,使我们能够自定义类的行为,让它表现得像内置类型(如列表、字符串、数字等)。

1.1 魔术方法的特点

  • 方法名前后都有双下划线 __xxx__
  • 一般由 Python 解释器在特定操作时自动调用,无需手动调用
  • 可以实现运算符重载、对象转换、容器行为等

2. 常见的对象生命周期魔术方法

2.1 __init__ —— 构造方法

在创建对象时初始化实例属性。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person("Alice", 30)  # 自动调用 __init__

2.2 __del__ —— 析构方法

对象被销毁时调用,用于释放资源。

class FileHandler:
    def __init__(self, filename):
        self.file = open(filename, 'w')
    def __del__(self):
        self.file.close()
        print("文件已关闭")

2.3 __repr____str__

  • __repr__:面向开发者的字符串表示,通常用于调试。repr(obj) 或交互模式中直接输出对象时调用。
  • __str__:面向用户的字符串表示,print(obj)str(obj) 时调用。
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
    def __str__(self):
        return f"({self.x}, {self.y})"

p = Point(3, 4)
print(repr(p))  # Point(3, 4)
print(str(p))   # (3, 4)
print(p)        # (3, 4)  (调用 __str__)

3. 布尔值与真值测试

3.1 __bool__

决定对象在布尔上下文(如 if obj:)中的真假。
如果没有定义 __bool__,Python 会尝试调用 __len__,若也没有则默认为 True

class MyCollection:
    def __init__(self, data):
        self.data = data
    def __bool__(self):
        return len(self.data) > 0

col1 = MyCollection([1, 2, 3])
col2 = MyCollection([])
print(bool(col1))  # True
print(bool(col2))  # False

4. 容器行为魔术方法(基础)

可以让类表现得像列表、字典等容器。

4.1 __len__

定义 len(obj) 的返回值。

class Bag:
    def __init__(self, items):
        self.items = items
    def __len__(self):
        return len(self.items)

bag = Bag([1, 2, 3])
print(len(bag))  # 3

4.2 __getitem____setitem__

支持下标访问和赋值。

class SimpleList:
    def __init__(self, items):
        self.items = items
    def __getitem__(self, index):
        return self.items[index]
    def __setitem__(self, index, value):
        self.items[index] = value

sl = SimpleList([10, 20, 30])
print(sl[1])  # 20
sl[1] = 99
print(sl[1])  # 99

5. 实际应用案例:自定义数值向量

class Vector:
    def __init__(self, *components):
        self.components = list(components)
    def __len__(self):
        return len(self.components)
    def __getitem__(self, index):
        return self.components[index]
    def __repr__(self):
        return f"Vector{ tuple(self.components) }"
    def __bool__(self):
        return any(self.components)  # 任一分量非零即为 True

v = Vector(0, 5, 0)
print(v)        # Vector(0, 5, 0)
print(len(v))   # 3
print(bool(v))  # True

6. 常见错误与注意事项

  • 魔术方法必须严格使用双下划线包围,拼写错误会导致方法不被调用
  • __init__ 不应有返回值(返回非 None 会报错)
  • __repr__ 应尽量返回一个有效的 Python 表达式字符串,便于调试
  • 如果定义了 __bool__,不要再依赖 __len__ 来决定真值,避免逻辑混乱

7. 课后练习

  1. Rectangle 类实现 __str____repr__,使打印和交互模式输出更直观。
  2. 为自定义的 Stack 类实现 __len____bool__,支持 len(stack)if stack: 判断。
  3. 设计一个 Table 类,实现 __getitem__ 支持下标访问行数据。

总结

  • 魔术方法是 Python 面向对象的重要特性,能显著增强类的功能和可用性
  • 常用基础魔术方法包括构造/析构、字符串表示、布尔值、容器行为等
  • 正确使用魔术方法可以让自定义类自然地融入 Python 语法和习惯用法

下一集我们将深入学习 常用魔术方法,掌握更多运算符重载与特殊功能的实现。

« 上一篇 抽象类与接口 下一篇 » 常用魔术方法