Python魔法方法

Python魔法方法

一、 概述

1、 魔法方法

从入门到进阶,一个很重要的点就是Python中的魔法方法,魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动发生的。它们经常是两个下划线包围来命名的(比如 __init__/__new__等等),Python的魔法方法是非常强大的。

如果你学习过Java,那你会发现Python中的魔法方法像是Java中的重载,Python中的魔法方法可以理解为:对类中的内置方法的重载,注意这里不是重写。

举个例子,Python中有个比较操作符==用来比较两个变量的大小,而这个操作符是通过内置函数__eq__来实现的,所以我们只需要通过改变这个内置函数代码,就可以改变重新定义这个操作符的行为。

如,我们需要比较一个字符串的长度是否相同,我们可以这么做:

class MyStr(str):

    def __eq__(self, __x: object) -> bool:
        return len(self) == len(__x)

a, b = MyStr("123"), MyStr("abc")
print(a == b)  # 返回True

再举个例子,Python中的__new__方法是对象实例化时调用的第一个方法,该方法仅读取一个cls参数后再把其他参数都传给用于指明对象初始化行为的__init__方法,也就是说我们可以在一个对象初始化之前进行其他操作,比如检查是否合法等;而另一个方法__del__可以用来销毁对象,定义了对象被垃圾回收的行为,我们可以利用该方法进行资源回收等操作。

我们可以通过重写__new__方法实现一个单例模式,在每次实例化之前检查该对象是否有已有实例。

class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            print("这个类没有创建")
            cls._instance = super().__new__(cls, *args, **kwargs)  # 使用父类的方法来创建类
        print("这个类已经创建")
        return cls._instance

s = Singleton()
s2 = Singleton()  # s 和 s2 是同一个类,其共用一个内存地址

2、 常用的魔法方法

通过这两个例子相信你已经对Python的魔法方法比较理解了,但是Python中的魔法方法远不止两三个,这里有一些比较常用的魔法方法,供我们学习。

二、 构造方法

我们最为熟知的基本的魔法方法就是 __init__ ,我们可以用它来指明一个对象初始化的行为。然而,当我们调用 x = SomeClass() 的时候, __init__ 并不是第一个被调用的方法。事实上,第一个被调用的是__new__,这个方法才真正地创建了实例。当这个对象的生命周期结束的时候,__del__会被调用。让我们近一步理解这三个方法:

1、 __new__

__new__ 是对象实例化时第一个调用的方法,它只取下 cls 参数,并把其他参数传给 __init____new__很少使用,但是也有它适合的场景,尤其是当类继承自一个像元组或者字符串这样不经常改变的类型的时候。 Python文档 中 有详细的说明。

比如,我们可以使用__new__方法来实现单例模式,只创建一个类。

2、 __init__

类的初始化方法。它获取任何传给构造器的参数(比如我们调用 x = SomeClass(10, 'foo')__init__ 就会接到参数 10 和 ‘foo’ 。 __init__ 在Python的类定义中用的最多。

3、 __del__

__new____init__是对象的构造器, __del__ 是对象的销毁器。它并非实现了语句 del x (因此该语句不等同于 x.__del__())。而是定义了当对象被垃圾回收时的行为。 当对象需要在销毁时做一些处理的时候这个方法很有用,比如 socket 对象、文件对象。但是需要注意的是,当Python解释器退出但对象仍然存活的时候,__del__并不会 执行。 所以养成一个手工清理的好习惯是很重要的,比如及时关闭连接。

使用案例:

from httpx import Client

class Crawl:
    def __init__(self) -> None:
        """初始化类,有点像C++里面的构造函数"""
        print("正在开启连接")
        self.client = Client() 
    
    def use(self):
        print("正在使用连接", self.client.is_closed)
    
    def __del__(self) -> None:
        """在类关闭的时候,释放内存,有点像C++里面的析构函数"""
        print("正在关闭连接")
        if self.client.is_closed:
            self.client.close()
            del self.client

c = Crawl()
c.use()

三、 操作符

1、 简介

使用Python魔法方法的一个巨大优势就是可以构建一个拥有Python内置类型行为的对象。这意味着你可以避免使用非标准的、丑陋的方式来表达简单的操作。 在一些语言中,这样做很常见:

if instance.equals(other_instance):
    # do something

你当然可以在Python也这么做,但是这样做让代码变得冗长而混乱。不同的类库可能对同一种比较操作采用不同的方法名称,这让使用者需要做很多没有必要的工作。运用魔法方法的魔力,我们可以定义方法 __eq__

if instance == other_instance:
    # do something

这是魔法力

  • 7
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SteveKenny

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值