> 技术文档 > Python零基础入门:魔法方法详解_python魔法方法

Python零基础入门:魔法方法详解_python魔法方法


一、什么是魔法方法

魔法方法(Magic Methods)是Python中一种特殊的方法,它们以双下划线(__)开头和结尾(如__init____str__等)。魔法方法允许你定义类在特定情况下的行为,例如初始化、字符串表示、运算符重载等。

二、常见的魔法方法分类

1. 构造和初始化

  • __new__(cls, [...]): 创建实例时调用的第一个方法

  • __init__(self, [...]): 实例初始化方法

  • __del__(self): 析构方法,当实例被销毁时调用

2. 字符串表示

  • __str__(self): 定义str()print()的行为

  • __repr__(self): 定义repr()的行为,通常用于调试

  • __format__(self, format_spec): 定义format()的行为

3. 比较运算符

  • __eq__(self, other): 定义==行为

  • __ne__(self, other): 定义!=行为

  • __lt__(self, other): 定义<行为

  • __le__(self, other): 定义<=行为

  • __gt__(self, other): 定义>行为

  • __ge__(self, other): 定义>=行为

4. 算术运算符

  • __add__(self, other)+

  • __sub__(self, other)-

  • __mul__(self, other)*

  • __truediv__(self, other)/

  • __floordiv__(self, other)//

  • __mod__(self, other)%

  • __pow__(self, other)**

5. 容器类型方法

  • __len__(self): 定义len()行为

  • __getitem__(self, key): 定义self[key]行为

  • __setitem__(self, key, value): 定义self[key] = value行为

  • __delitem__(self, key): 定义del self[key]行为

  • __contains__(self, item): 定义in操作符行为

6. 可调用对象

  • __call__(self, [...]): 使实例可以像函数一样被调用

7. 上下文管理

  • __enter__(self): 定义with语句开始时的行为

  • __exit__(self, exc_type, exc_val, exc_tb): 定义with语句结束时的行为

三、魔法方法练习题

1. __init__ - 构造初始化方法

这是最常见的魔法方法,用于初始化新创建的对象。

class Dog: def __init__(self, name, age): self.name = name # 设置实例属性 self.age = age print(f\"一只名叫{name}的狗出生了!\")# 创建实例时会自动调用__init__my_dog = Dog(\"旺财\", 3) # 输出:一只名叫旺财的狗出生了!print(my_dog.name) # 输出:旺财

2. __str__ vs __repr__ - 字符串表示

  • __str__:给用户看的友好字符串

  • __repr__:给开发者看的准确字符串(通常可以用来重建对象)

    class Point: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f\"这是一个点({self.x}, {self.y})\" def __repr__(self): return f\"Point({self.x}, {self.y})\"p = Point(1, 2)print(p) # 输出:这是一个点(1, 2)print(str(p)) # 输出:这是一个点(1, 2)print(repr(p)) # 输出:Point(1, 2)

3. 算术运算符

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 __sub__(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\"Vector({self.x}, {self.y})\"v1 = Vector(2, 3)v2 = Vector(1, 1)print(v1 + v2) # Vector(3, 4)print(v1 - v2) # Vector(1, 2)print(v1 * 3) # Vector(6, 9)

4. 比较运算符

class Student: def __init__(self, name, score): self.name = name self.score = score # 等于 == def __eq__(self, other): return self.score == other.score # 大于 > def __gt__(self, other): return self.score > other.score # 小于等于 <= def __le__(self, other): return self.score  bob) # Trueprint(alice <= bob) # False

5. __len__ - 获取长度

class Playlist: def __init__(self, songs): self.songs = list(songs) def __len__(self): return len(self.songs)my_playlist = Playlist([\"Song1\", \"Song2\", \"Song3\"])print(len(my_playlist)) # 输出:3

6. __getitem__ 和 __setitem__ - 索引访问

class Playlist: def __init__(self, songs): self.songs = list(songs) def __getitem__(self, index): return self.songs[index] def __setitem__(self, index, value): self.songs[index] = valuepl = Playlist([\"A\", \"B\", \"C\"])print(pl[1]) # 输出:Bpl[1] = \"New Song\"print(pl[1]) # 输出:New Song

7. __iter__ - 使对象可迭代

class CountDown: def __init__(self, start): self.start = start def __iter__(self): current = self.start while current > 0: yield current current -= 1for num in CountDown(5): print(num) # 输出:5 4 3 2 1

8. __call__ - 使实例可调用

class Adder: def __init__(self, n): self.n = n def __call__(self, x): return self.n + xadd5 = Adder(5)print(add5(3)) # 输出:8print(add5(10)) # 输出:15

9. __enter__ 和 __exit__ - 上下文管理

class Timer: def __enter__(self): import time self.start = time.time() return self def __exit__(self, exc_type, exc_val, exc_tb): import time self.end = time.time() print(f\"耗时: {self.end - self.start:.2f}秒\")with Timer(): # 模拟耗时操作 sum(i for i in range(1000000))# 输出:耗时: 0.12秒

 

四、综合练习案例

实现一个简单的分数类

class Fraction: def __init__(self, numerator, denominator=1): self.numerator = numerator self.denominator = denominator self._simplify() def _simplify(self): \"\"\"约分分数\"\"\" def gcd(a, b): while b: a, b = b, a % b return a common_divisor = gcd(self.numerator, self.denominator) self.numerator //= common_divisor self.denominator //= common_divisor def __add__(self, other): new_num = self.numerator * other.denominator + other.numerator * self.denominator new_den = self.denominator * other.denominator return Fraction(new_num, new_den) def __sub__(self, other): new_num = self.numerator * other.denominator - other.numerator * self.denominator new_den = self.denominator * other.denominator return Fraction(new_num, new_den) def __mul__(self, other): return Fraction(self.numerator * other.numerator, self.denominator * other.denominator) def __truediv__(self, other): return Fraction(self.numerator * other.denominator, self.denominator * other.numerator) def __eq__(self, other): return (self.numerator == other.numerator and  self.denominator == other.denominator) def __str__(self): return f\"{self.numerator}/{self.denominator}\" def __repr__(self): return f\"Fraction({self.numerator}, {self.denominator})\"# 使用示例f1 = Fraction(1, 2)f2 = Fraction(1, 3)print(f1 + f2) # 输出:5/6print(f1 - f2) # 输出:1/6print(f1 * f2) # 输出:1/6print(f1 / f2) # 输出:3/2print(f1 == f2) # 输出:False

五、魔法方法总结

  1. 核心概念

    • 魔法方法是Python中特殊的方法,用于自定义类的行为

    • 它们以双下划线开头和结尾

    • Python在特定情况下自动调用这些方法

  2. 主要用途

    • 初始化对象(__init____new__)

    • 字符串表示(__str____repr__)

    • 运算符重载(__add____sub__等)

    • 容器行为(__len____getitem__等)

    • 上下文管理(__enter____exit__)

    • 可调用对象(__call__)

  3. 最佳实践

    • __repr__应该返回一个可以用来重建对象的字符串

    • __str__应该返回一个用户友好的字符串

    • 实现比较方法时保持一致性

    • 运算符重载应该保持直观的行为

  4. 注意事项

    • 不要滥用魔法方法,保持行为直观

    • 某些魔法方法需要成对实现(如__eq____hash__

    • 继承内置类型时要小心,可能需要重写多个魔法方法

  5. 学习建议

    • 从简单的__init____str__开始

    • 逐步尝试运算符重载

    • 理解Python的数据模型如何工作

    • 查看内置类型的源代码学习标准实现

  6. 魔法方法总结表

魔法方法 描述 触发方式 __init__(self) 对象初始化 obj = Class() __str__(self) 用户友好字符串表示 str(obj)print(obj) __repr__(self) 开发者字符串表示 repr(obj) __add__(self, other) 加法运算 + obj1 + obj2 __sub__(self, other) 减法运算 - obj1 - obj2 __mul__(self, other) 乘法运算 * obj1 * obj2 __eq__(self, other) 等于比较 == obj1 == obj2 __lt__(self, other) 小于比较 < obj1 < obj2 __len__(self) 获取长度 len(obj) __getitem__(self, key) 索引访问 obj[key] __setitem__(self, key, value) 索引赋值 obj[key] = value __iter__(self) 迭代支持 for x in obj __call__(self, ...) 使实例可调用 obj() __enter__(self)__exit__(self) 上下文管理 with obj:

记住这些魔法方法的关键是理解它们何时被Python自动调用。通过实现这些方法,你可以让你自定义的类表现得像Python内置类型一样自然。