# Python 魔术方法(魔法方法)超详细讲解

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("执行代码")

七、属性相关魔术方法

控制对象属性的获取、设置、删除:

  1. __getattr__(self, name):获取不存在的属性时触发
  2. __setattr__(self, name, value):设置属性时触发
  3. __delattr__(self, name):删除属性时触发

八、魔术方法核心总结

  1. 格式__方法名__(双下划线包裹)
  2. 特点自动触发,不需要手动调用
  3. 用途
    • 初始化/销毁对象
    • 自定义打印、运算、容器行为
    • 实现 with、函数调用等高级语法
  4. 最常用__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__

流程:

  1. A() → 先调用 A.__new__(A)
  2. __new__ 内部通过父类创建实例并返回
  3. Python 拿到返回的实例,自动调用 __init__

三、关键点

  1. 第一个参数是 cls (当前类),不是 self
  2. 必须返回一个实例
    • 返回本类实例:才会触发 __init__
    • 返回其他类实例:不会触发本类 __init__
  3. 继承自 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__,只有单例、控制实例创建、元类时才会用到
相关推荐
2501_933329552 小时前
技术深度拆解:Infoseek舆情处置系统的全链路架构与核心实现
开发语言·人工智能·自然语言处理·架构
妮妮喔妮2 小时前
supabase的webhook报错
开发语言·前端·javascript
我的xiaodoujiao2 小时前
API 接口自动化测试详细图文教程学习系列11--Requests模块3--测试练习
开发语言·python·学习·测试工具·pytest
Polar__Star2 小时前
C#怎么使用并发集合 C#ConcurrentDictionary和ConcurrentQueue线程安全集合怎么用【进阶】
jvm·数据库·python
xiaoye-duck2 小时前
【C++:C++11】C++11新特性深度解析:从类新功能、Lambda表达式到包装器实战
开发语言·c++·c++11
qq_12084093712 小时前
Three.js 大场景分块加载实战:从全量渲染到可视集调度
开发语言·javascript·数码相机
csbysj20202 小时前
Pandas 常用函数
开发语言
TechWayfarer3 小时前
攻防对抗:利用IP段归属查询工具快速封禁攻击源——3步联动防火墙(附脚本)
python·网络协议·tcp/ip·安全
m0_493934533 小时前
Go语言中 & 与 - 的本质区别及指针使用详解
jvm·数据库·python