Python 魔术方法(魔法方法)超详细讲解
魔术方法 是 Python 中以双下划线 __ 开头和结尾 的特殊方法(比如 __init__、__str__),它们会在特定操作自动触发,不需要手动调用,能让自定义类实现 Python 内置类型的行为(比如加减乘除、打印、索引取值)。
它们的核心作用:让自定义对象更符合 Python 语法习惯,实现运算符重载、容器行为、上下文管理等功能。
一、最基础、最常用的魔术方法
1. __init__(self, ...):初始化方法
触发时机 :创建对象时自动调用
python
class Person:
# 初始化对象属性
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("小明", 20) # 自动调用 __init__
2. __str__(self):打印对象字符串
触发时机 :print(对象)、str(对象) 时自动调用
作用:自定义对象的打印信息(默认打印内存地址)
python
class Person:
def __init__(self, name):
self.name = name
def __str__(self):
return f"人物:{self.name}"
p = Person("小红")
print(p) # 输出:人物:小红
3. __repr__(self):开发用字符串表示
触发时机 :在控制台直接输入对象、repr(对象) 时触发
区别 :__str__ 给用户看,__repr__ 给开发者看
python
def __repr__(self):
return f"Person('{self.name}')"
二、生命周期相关魔术方法
1. __new__(cls):创建对象
比 __init__ 更早执行,负责真正创建对象(很少重写,单例模式会用到)。
2. __del__(self):销毁对象
触发时机:对象被垃圾回收时自动调用(程序结束、手动删除对象)。
三、容器/序列魔术方法(列表/字典行为)
让你的自定义类像列表、字典一样使用:
| 魔术方法 | 触发操作 | 示例 |
|---|---|---|
__len__(self) |
len(对象) |
返回元素个数 |
__getitem__(self, key) |
obj[key] |
索引/键取值 |
__setitem__(self, key, value) |
obj[key] = x |
赋值 |
__delitem__(self, key) |
del obj[key] |
删除元素 |
__contains__(self, item) |
item in obj |
判断成员关系 |
示例:自定义一个类,用起来像列表
python
class MyList:
def __init__(self):
self.data = []
# len(obj)
def __len__(self):
return len(self.data)
# obj[0]
def __getitem__(self, index):
return self.data[index]
# obj[0] = 100
def __setitem__(self, index, value):
self.data[index] = value
ml = MyList()
ml.data = [1,2,3]
print(len(ml)) # 自动调用 __len__ → 3
print(ml[0]) # 自动调用 __getitem__ → 1
四、运算符重载魔术方法(加减乘除、比较)
让自定义对象支持 + - * / == > < 等运算:
1. 算术运算符
| 方法 | 操作 |
|---|---|
__add__(self, other) |
obj + other |
__sub__(self, other) |
obj - other |
__mul__(self, other) |
obj * other |
__truediv__(self, other) |
obj / other |
2. 比较运算符
| 方法 | 操作 |
|---|---|
__eq__(self, other) |
== |
__lt__(self, other) |
< |
__gt__(self, other) |
> |
示例:对象相加
python
class Number:
def __init__(self, num):
self.num = num
# 支持 + 运算
def __add__(self, other):
return Number(self.num + other.num)
a = Number(5)
b = Number(3)
c = a + b # 自动调用 __add__
print(c.num) # 8
五、可调用对象:__call__(self)
触发时机 :把对象当成函数调用 时(obj())
python
class Test:
def __call__(self, x, y):
return x + y
t = Test()
print(t(1,2)) # 自动调用 __call__ → 3
六、上下文管理器:__enter__ / __exit__
支持 with 语句(像文件操作一样):
python
class MyContext:
def __enter__(self):
print("进入上下文")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文")
with MyContext():
print("执行代码")
七、属性相关魔术方法
控制对象属性的获取、设置、删除:
__getattr__(self, name):获取不存在的属性时触发__setattr__(self, name, value):设置属性时触发__delattr__(self, name):删除属性时触发
八、魔术方法核心总结
- 格式 :
__方法名__(双下划线包裹) - 特点 :自动触发,不需要手动调用
- 用途 :
- 初始化/销毁对象
- 自定义打印、运算、容器行为
- 实现
with、函数调用等高级语法
- 最常用 :
__init__、__str__、__len__、__getitem__、__add__
总结
魔术方法是 Python 面向对象的核心特性 ,它让自定义类能无缝适配 Python 的原生语法,写出更简洁、更优雅的代码。
你只需要记住:Python 的内置操作,底层都是靠魔术方法实现的。
1. __new__ 方法介绍
__new__ 是 Python 里真正创建实例对象 的魔术方法,比 __init__ 更早执行。
一句话总结:
__new__负责造对象(分配内存)__init__负责初始化对象(给属性赋值)
一、基本区别
| 方法 | 作用 | 调用时机 | 返回值 |
|---|---|---|---|
__new__ |
创建实例 | 类被实例化时最先调用 | 必须返回一个对象 |
__init__ |
初始化实例 | __new__ 返回对象后才调用 |
不能返回任何值(必须是 None) |
二、最简单示例
python
class A:
def __new__(cls, *args, **kwargs):
print("执行 __new__")
# 调用父类 object 的 __new__ 真正创建对象
instance = super().__new__(cls)
return instance
def __init__(self):
print("执行 __init__")
a = A()
输出顺序:
执行 __new__
执行 __init__
流程:
A()→ 先调用A.__new__(A)__new__内部通过父类创建实例并返回- Python 拿到返回的实例,自动调用
__init__
三、关键点
- 第一个参数是
cls(当前类),不是self - 必须返回一个实例
- 返回本类实例:才会触发
__init__ - 返回其他类实例:不会触发本类
__init__
- 返回本类实例:才会触发
- 继承自
object,默认已经实现,平时不用重写
四、经典用法:单例模式
这是 __new__ 最常用的场景------保证整个程序只产生一个实例。
python
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
a = Singleton()
b = Singleton()
print(a is b) # True 同一个对象
五、一个"反常"例子
如果 __new__ 不返回本类实例,__init__ 就不会执行:
python
class A:
def __new__(cls):
print("__new__")
return 123 # 返回 int,不是 A 的实例
def __init__(self):
print("__init__") # 永远不会执行
a = A()
print(a) # 123
六、和 __init__ 参数关系
__new__ 和 __init__ 会共享传入的参数:
python
class A:
def __new__(cls, name):
print("__new__:", name)
return super().__new__(cls)
def __init__(self, name):
print("__init__:", name)
a = A("Tom")
极简总结
__new__:造对象,静态方法,返回实例__init__:初始化,实例方法,无返回值- 平时不用写
__new__,只有单例、控制实例创建、元类时才会用到