Python魔法方法指南:让你的类如丝般顺滑 ✨
在Python的世界里,双下划线不是密码,而是打开魔法之门的钥匙。🔑

当我们想让自定义类像内置类型一样优雅工作——len(obj)能返回长度、print(obj)展示友好信息、obj1 + obj2实现运算时,魔法方法(Magic Methods) 就是实现这些魔法的咒语。
它们以双下划线开头和结尾(如__init__),是Python面向对象编程的”隐藏技能树”,这些方法允许你自定义类的行为,使其能够与Python的内置操作符和函数一起工作。

生命起始符:__init____new__

  • 实例化方法 __new__(cls) 中定义的操作会在创建类实例时执行,返回一个没有初始化过的实例对象,__new__控制对象创建过程(构造函数)

  • 初始化方法 __init__(self) 中定义的操作会在类初始化时被调用,__init__管理对象初始化(初始化器)。

初始化方法都是在实例化方法之后执行,例如MyClass(10)的执行过程就是先调用__new__方法返回一个值为空的MyClass实例对象,然后调用__init__对这个实例对象进行初始化,最终形成一个完整的实例化对象。
注意:如果__new__方法返回的不是当前类的实例对象就会跳过__init__方法的执行。

1
2
3
4
5
6
7
8
9
class MyClass:
def __new__(cls, *args):
return super().__new__(cls)
def __init__(self, value=1):
self.num = value
print("Initialized with", self.num)

obj1 = MyClass(10) # 输出: Initialized with 10
obj2 = MyClass() # 输出: Initialized with 1

形象大使:__str__

  • 字符串表示的 __str__ ,在 __str__ 中定义对对象使用str的结果,定义str()和print()调用此对象的结果
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Student:
    def __init__(self, first, last):
    self.first = first
    self.last = last
    def __str__(self):
    # 返回字符串表示形式
    return f"{self.first} {self.last}"
    student1 = Student("John", "Doe")
    print(student1) # 输出: John Doe
    full_name = str(student1) # 调用__str__方法
    print(full_name) # 输出: John Doe
    print(student1.__str__()) # 直接调用__str__方法,输出: John Doe

容器改造术: __len____getitem__

  • __len__:定义对对象使用len()的行为
  • __getitem__:定义通过索引获取实例内容的方式
1
2
3
4
5
6
7
8
9
10
11
12
13
class JurassicPark:
def __init__(self):
self.dinos = ["T-Rex", "Velociraptor", "Triceratops"]

def __len__(self):
return len(self.dinos) # 返回园区恐龙数量

def __getitem__(self, index):
return f"🦕 {self.dinos[index]}"

park = JurassicPark()
print(len(park)) # 3
print(park[1]) # 🦕 Velociraptor

运算符重载:数学之美

  • 定义两个实例对象的算数运算规则
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class Vector:
    def __init__(self, x, y):
    self.x = x
    self.y = y

    def __add__(self, other):
    """实现向量加法"""
    return Vector(self.x + other.x, self.y + other.y)

    def __mul__(self, scalar):
    """实现向量标量乘法"""
    return Vector(self.x * scalar, self.y * scalar)

    def __str__(self):
    return f"({self.x}, {self.y})"

    v1 = Vector(2, 3)
    v2 = Vector(1, 4)
    print(v1 + v2) # (3, 7)
    print(v1 * 3) # (6, 9)

对象比较: __eq__

  • 用于比较的 __eq__,定义两个对象间使用 == 的行为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Student:
    def __init__(self, id, name):
    self.id = id
    self.name = name
    def __eq__(self, other):
    # 定义 `==` 方法用于比较两个实例是否相等,这里定义为id相同就认为是同一个Student
    return self.id == other.id

    student1 = Student("10086","Alice")
    student2 = Student("10086", "艾丽丝")
    print(student1 == student2) # 输出: True,因为id相同

上下文管理器: __enter____exit__

  • 上下文管理器:记录with的生命周期,在with开始使用前执行__enter__在with结束使用后执行__exit__
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class TimeTravel:
    def __enter__(self):
    print("⏳ 开启时空隧道...")
    return self

    def __exit__(self, exc_type, exc_val, exc_tb):
    print("⌛️ 关闭时空隧道")

    with TimeTravel() as portal:
    print("正在穿越白垩纪...")