Python面向对象——类的魔法方法

本文讲述Python面向对象的高级知识------类的魔法方法。阅读本文有助于理解源码!

一、什么是魔法方法

魔法方法(Magic Methods)是 Python 类中以双下划线开头和结尾(如 __init__)的特殊方法,由 Python 解释器在特定语法或操作触发时自动调用。它们定义了对象在语言层面的行为协议(Protocol),使得自定义类能够模拟内置类型(如 intlistdict)的语义,从而支持运算符重载、容器行为、上下文管理、字符串表示等核心功能。

看完这个定义,你肯定可以想到 __init__方法 没错这就是最常见的一个魔法方法,在类实例化时才会执行。

所以只要是以 __func__这样格式的就是魔法方法。

由于魔法方法太多,本文只挑选了六个常用的进行讲解。

python 复制代码
class Student:
    def __init__(self):
        self.name = '小白'
        self.gender = '男'
        self.age = 18


stu = Student()

二、四个魔法方法

【1】new()方法

new()方法是在 Python 中定义一个类的时候可以定义的一个特殊方法。

它被用来创建一个类的新实例(对象)。

你可能认为创建一个新的实例 一般是通过调用类的构造函数 init() 来完成的

然而,通过类名()创建对象时,在自动执行 init() 方法前,会先执行 object.new 方法,内存中开辟对象空间并返回该对象然后,Python 才会调用 init() 方法来对这个新实例进行初始化。

小例子

运行这段代码,你会发现先打印__new__里面的语句,再打印__init__的语句。

**注意:**一定要返回 object.new(cls) 这一句。为什么呢? 因为上面提到过 new 要在内存开辟对象空间并返回该对象。如果不返回,那么init方法中拿不到这个对象就无法进行赋值,就不会执行该方法,读者可以将这句注释 再运行看看

python 复制代码
class Student(object):
    def __new__(cls, *args, **kwargs):
        print("执行__new__方法")
        return object.__new__(cls) # 如果没有这行回怎么样

    def __init__(self):
        print("执行__init__方法")
        self.name = '小白'
        self.gender = '男'
        self.age = 18


stu = Student()

new_()方法的主要作用是创建实例对象,它可以被用来控制实例的创建过程。相比之下,init() 方法主要用于初始化实例对象。

new() 方法在设计模式中常常与单例模式结合使用,用于创建一个类的唯一实例。单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。

例子:

python 复制代码
class Singleton:
    _instance = None
    
    # 通过注释这段函数 运行两次
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls)
        return cls._instance


# 创建实例
obj1 = Singleton()
obj2 = Singleton()

# 检查是否为同一个实例
print(obj1 is obj2)  # 输出: True

【2】__str__方法

改变对象的字符串显示。默认打印一个对象是返回其内存地址

如果我们使用 __str__方法 可以自定义我们想返回的内容

触发时机 : str(对象 ) print(对象)

例子:

注:这个str方法经常使用!!!

python 复制代码
class Student(object):

    def __init__(self):
        self.name = '小白'
        self.gender = '男'
        self.age = 18

    def __str__(self):
        return f"学生信息:姓名:{self.name},性别:{self.gender} 年龄:{self.age}"


stu = Student()

print(stu)
print(str(stu))

【3】eq 方法

用于比较两个类是否相等

触发时机 当对两个对象进行 == 运算时

重点理解:走谁的eq方法

python 复制代码
class Student(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
        self.age = 18

    def __eq__(self, other):
        print(f"走{self.name}的eq方法")
        return self.name == other.name


stu1 = Student('小白', '男')
stu2 = Student('小灰','女')
stu3 = Student('小黑','女')

print(stu1 == stu2)

【4】__item__系列 (重点)

在没有item系列魔法方法前,我们操作对象只能通过 对象实例.xxx

那有没有一种办法可以让我们像操作字典一样操作对象呢

在__item__系列中一共有3个方法需要我们掌握

getitem、setitem、delitem 对应三种操作 取值 赋值 删除值

例子:

python 复制代码
class Cache:
    def __init__(self):
        self.data = {}

    def __getitem__(self, key):
        return self.data[key]

    def __setitem__(self, key, value):
        self.data[key] = value

    def __delitem__(self, key):
        del self.data[key]

    def __contains__(self, key):
        return key in self.data

在上述例子中,我们创建了一个名为 Cache 的自定义类,并实现了 getitemsetitemdelitemcontains 这些特殊方法。

使用这个自定义的缓存类,我们可以像操作字典一样操作缓存数据,例如:

python 复制代码
cache = Cache()  
#存储数据  
cache['key1'] = 'value1'  
cache['key2'] = 'value2'  
  
#获取数据  
print(cache['key1'])  
print(cache['key2'])  
  
print("key1" in cache)  
  
del cache['key1']  
  
print("key1" in cache)

通过实现这一系列特殊方法,我们可以使用类似于字典的语法来访问和操作缓存对象。这样,我们可以更方便地存储、获取和删除缓存数据,同时也可以使用其他字典操作,如检查键是否存在。

三、总结

目前遇见最多的是str喝item系列魔法方法,后续这个文章还会继续更新我遇到的且有用的魔法方法。举个例子,我在研究simplejwt的源码发现底层就是使用了 str和item系列方法

相关推荐
笨拙的老猴子2 分钟前
[特殊字符] Java GC机制详解:G1、ZGC、Shenandoah全面解析与版本演进对比
java·开发语言
bellus-3 分钟前
ubuntu26测试win10的ollama大模型性能
python
水木流年追梦4 分钟前
大模型入门-Reward 奖励模型训练
开发语言·python·算法·leetcode·正则表达式
JavaWeb学起来4 分钟前
Python学习教程(六)数据结构List(列表)
数据结构·python·python基础·python教程
liuyunshengsir17 分钟前
PyTorch 动态量化(Dynamic Quantization)
人工智能·pytorch·python
电子云与长程纠缠26 分钟前
UE5制作六边形包裹球体效果
开发语言·python·ue5
砍材农夫32 分钟前
物联网 基于netty构建mqtt协议规范(遗嘱与保留消息)
java·开发语言·物联网·netty
DFT计算杂谈35 分钟前
KPROJ编译教程
java·前端·python·算法·conda
froginwe111 小时前
Python3 迭代器与生成器
开发语言
xiaoshuaishuai81 小时前
C# 签名异常与Gas预估失败调试方案
开发语言·网络·tcp/ip·c#