Python——魔术方法
1. 基础概念
1.1 什么是魔术方法
魔术方法是 Python 官方内置的特殊方法,统一语法格式为 前后双下划线包裹:__xxx__,是面向对象编程的核心底层语法。
它无需开发者手动调用,会在对应代码场景触发时自动执行,专门用于改写自定义类的默认底层行为。
1.2 为什么需要魔术方法
Python 原生仅支持字符串、列表、数字等内置数据类型的打印、运算、下标取值、长度获取等操作。而我们自己定义的类对象,默认不具备这些能力,直接操作会报错。
魔术方法的核心作用:给自定义对象赋予原生语法能力,通过重写对应魔术方法,自定义对象可以像内置对象一样,实现打印、加减运算、大小比较、下标操作、迭代等功能。
2. 核心魔术方法
2.1 __init__ 初始化方法
触发时机:实例化对象时 自动触发
作用:给对象初始化属性(赋值)
class Student:
# 创建对象自动执行
def __init__(self, name, age):
self.name = name
self.age = age
s = Student("小明", 18) # 自动触发 __init__
print(s.name, s.age)
2.2 __new__ 构造方法
触发时机:创建对象的第一步,最先执行,优先级高于 __init__
核心作用:向内存开辟空间、创建并返回空白对象
执行顺序:__new__ 先造对象 → __init__ 后赋值
__new__系统默认实现,不用自己写
2.3 __str__ 打印对象方法
触发时机:print(对象) 时自动触发
作用:自定义打印对象的内容,不再输出默认内存地址
无 __str__(原生默认效果)→ 打印内存地址
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
# 没有重写 __str__
s = Student("小红", 17)
# 直接打印:输出垃圾内存地址,看不到属性数据
print(s)
# 示例输出:<__main__.Student object at 0x0000023xxxxxxx>
有__str__
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
# 重写打印规则
def __str__(self):
return f"学生姓名:{self.name},年龄:{self.age}"
s = Student("小红", 17)
print(s) # 自动触发 __str__
# 输出:学生姓名:小红,年龄:17
2.4 __del__ 析构方法
触发时机:对象被销毁、程序结束、主动 del 删除时自动触发
作用:资源释放(关闭文件、关闭链接)
class Demo:
def __del__(self):
print("对象被销毁了,释放资源!")
d = Demo()
del d # 主动删除对象,触发 __del__
print("程序结束")
3. 运算符重载魔术方法
默认情况下,自定义类对象不支持任何数学运算,直接对两个对象进行加减乘除会直接报错。
运算符重载魔术方法作用:重写运算底层规则,让自定义对象支持 + - * / 大小比较。
3.1 算术运算符重载(以__add__为例)
没有重写 __add__,对象之间无法相加,代码运行直接抛异常。
class Person:
def __init__(self, height):
self.height = height
p1 = Person(170)
p2 = Person(180)
print(p1 + p2)
# 直接对象相加:无重载 【必报错】
# TypeError: unsupported operand type(s) for +: 'Person' and 'Person'
有重载(重写__add__)→ 正常运行
class Person:
def __init__(self, height):
self.height = height
# 重载加法运算:自定义对象相加规则
def __add__(self, other):
return self.height + other.height
p1 = Person(170)
p2 = Person(180)
print("重载后对象相加结果:", p1 + p2) # 自动触发 __add__
3.2逻辑运算符重载(以__gt__为例)
除数学运算外,自定义对象默认也无法正常比较大小、判断相等,需要重载对应魔术方法实现功能。
class Person:
def __init__(self, age):
self.age = age
def __gt__(self, other):
return self.age > other.age
p1 = Person(20)
p2 = Person(18)
print(p1 > p2) # True
对象默认用内存地址判断相等,哪怕属性完全一致也判定为不相等;重写 __eq__ 可实现按属性判等。
-
__lt__:适配小于号 < 比较
-
__eq__:自定义对象相等判断规则,判断两个对象是否相等(默认比内存地址,重写可比属性)
4. 容器类魔术方法(列表/字典行为模拟)
4.1 __len__ 长度
len(对象) 自动触发,必须返回数字
class MyList:
def __init__(self, data):
self.data = data
def __len__(self):
return len(self.data)
obj = MyList([1,2,3,4])
print(len(obj)) # 4
4.2 __getitem__ 取值 []
对象[下标] 自动触发
class MyList:
def __init__(self):
self.data = [10, 20, 30]
# 开启下标取值功能
def __getitem__(self, index):
# index 就是你传入的下标
return self.data[index]
obj = MyList()
print(obj[0]) # 自动触发 __getitem__,输出 10
print(obj[1]) # 输出 20
print(obj[2]) # 输出 30
4.3 __setitem__ 赋值 []
对象[下标] = 值 自动触发
class MyList:
def __init__(self):
self.arr = [10,20,30]
# 取值
def __getitem__(self, index):
return self.arr[index]
# 赋值
def __setitem__(self, index, value):
self.arr[index] = value
m = MyList()
print(m[0]) # 10
m[1] = 999
print(m.arr) # [10, 999, 30]
5. 迭代/上下文魔术方法
5.1 __iter__ 迭代器
核心作用:让自定义类对象支持 for 循环遍历,默认自定义对象无法被迭代,重写 __iter__ 即可拥有列表、元组一样的遍历能力。
触发时机:对对象执行 for 循环迭代时自动触发
使用规则:__iter__ 需要返回可迭代对象,通常配合 iter() 函数实现
class MyList:
def __init__(self):
self.data = [11, 22, 33, 44]
# 开启对象迭代能力
def __iter__(self):
# 返回可迭代对象
return iter(self.data)
# 实例化对象
obj = MyList()
# 普通for循环遍历,自动触发 __iter__
for item in obj:
print(item)
5.2 __enter__ / __exit__ 上下文管理器
核心作用:让自定义对象支持 with 语句 语法,自动完成「资源开启 + 资源关闭」,杜绝资源泄露(文件、网络连接常用)。
触发时机:
-
__enter__:进入 with 代码块时自动触发(开启资源)
-
__exit__:退出 with 代码块时自动触发(关闭资源,哪怕代码报错也会执行)
核心优势:无需手动写关闭代码,自动收尾,安全性极高。
class FileTool:
# 进入with块自动执行:开启资源
def __enter__(self):
print("1. 自动开启资源:打开文件")
return self # 返回对象,给as变量接收
# 退出with块自动执行:关闭资源
def __exit__(self, exc_type, exc_val, exc_tb):
print("2. 自动关闭资源:关闭文件")
# 无论代码是否报错,都会执行收尾操作
def read_data(self):
print("读取文件数据")
# with语法运行
with FileTool() as tool:
tool.read_data()
print("执行文件操作逻辑")
print("with代码块结束,资源自动释放完毕")
运行流程:进入with触发__enter__ → 执行内部业务代码 → 退出with触发__exit__自动收尾
场景:文件读写、数据库连接、网络请求连接,统一用上下文管理器自动释放资源。
6. 魔术方法汇总
|
魔术方法 |
触发场景 |
核心作用 |
|---|---|---|
|
__init__ |
创建对象 |
初始化属性 |
|
__new__ |
创建对象最先执行 |
开辟内存、造对象 |
|
__str__ |
print(对象) |
自定义打印内容 |
|
__del__ |
对象销毁 |
释放资源 |
|
__add__ |
对象 + 对象 |
加法重载 |
|
__sub__ |
对象 - 对象 |
减法重载 |
|
__gt__ |
对象 > 对象 |
大于比较 |
|
__eq__ |
对象 == 对象 |
相等判断 |
|
__len__ |
len(对象) |
获取自定义长度 |
|
__getitem__ |
对象[x] |
下标取值 |
|
__setitem__ |
对象[x]=y |
下标赋值 |
-
魔术方法 自动触发,不用手动调用
-
默认情况下,== 对比的是内存地址;重写 __eq__ 才能对比属性
更多推荐



所有评论(0)