关于魔术方法的理解与整理
魔术方法就是一个类/对象中的方法,和普通方法唯一的不同时,普通方法需要调用!而魔术方法是在特定时刻自动触发。
在Python中,所有以__
双下划线包起来的方法,都统称为"魔术方法"。
接下来简单介绍几种常见的魔术方法:
1、__init__:
最常见的就是__init__了,它是初始化的魔术方法,在初始化对象的时候触发,通俗来讲就是你创建了一个类Person,在你初始化对象p = Person()的时候系统自动触发。但是__init__并不是第一个触发的,__new__才是,后面会提到。
class Person:
def __init__(self,name):
print(self)
print('----->init',name)
p = Person('张三')
执行结果如下:
__init__中至少有一个self参数,用来接收对象。代码中我打印了self的值,可以看到是对象地址。在创建好对象并没有做其他操作的时候可以看到系统触发了__init__方法,并打印出值。那么,在开发过程中,如果我们需要在初始化对象前做一些操作的时候,可以重写__init__方法来实现。
2、__new__:
它是实例化的魔术方法,上面有提到,它是早于__init__之前触发的,实际上实例化对象的时候,它就会去申请内存开辟空间。__new__
是用来创建类并返回这个类的实例,而__init__
只是将传入的参数来初始化该实例。一般情况下我们不去动这个魔术方法。
class Person:
def __init__(self,name):
print(self)
print('----->init',name)
def __new__(cls, *args, **kwargs):
position = object.__new__(cls)
print('----->new',position)
return position
p = Person('张三')
执行结果如下:
可以看到,__new__的触发时间是早于__init__的。__new__至少有一个参数cls接收当前类,在new中我通过调用object对象的__new__方法,其作用就是去申请开辟空间,将return出来的值传给__init__。所以可以看到地址是一样的。__init__中的self参数就是通过__new__中的cls接收后传过去的。这块比较绕,不知道有没有说清楚。后面碰到了再细说,一般在开发过程中不会去动这个方法,让系统自动触发就好了。
3、__call__:
这个方法就比较好理解了,它是调用对象的魔术方法。它的作用就是在你想把对象当成函数一样调用的时候触发。
class Person:
def __init__(self,name):
print('----->init',name)
def __call__(self, *args, **kwargs):
print('----->call')
p = Person('张三')
p() #把p对象当成函数一样调用
执行结果如下:
可以看到我把对象p调用方式写成函数的调用时,__call__被触发。在开发中可以将一些复杂的过程进行合并操作,减少调用的步骤,方便使用。__call__中至少有一个参数self接收对象,其余参数可以根据情况自行调整。
4、__del__:
它被称为析构魔术方法,怎么理解呢?就好比你创建了一个对象,当它不被引用的时候,系统自动触发__del__,就跟垃圾回收机制一样,这个对象没人用,系统会将它自动回收。(比喻解释一下,当然垃圾回收机制可不是简简单单三言两语)。它的参数也是一个self接收对象,其余自行决定。这个就不做具体的代码实现了,一般情况下不要去重写这个方法,以免影响python解释器回收空间的时候报错或者触发不到。
5、__str__:
这个看'str'知其意,它在对实例使用str()的时候触发,返回一个该实例的字符串。
class Person:
def __init__(self,name):
self.name = name
print('----->init',name)
def __str__(self):
return self.name
p = Person('张三')
print(p) #没有重写__str__前,<__main__.Person object at 0x0000000002950D08>
执行结果如下:
可以看到,在没有重写__str__之前,打印对象名返回的是地址,在开发过程中如果想看对象的更多信息我们就可以重写__str__方法了,要注意的是,它的返回值必须是字符串。
以上就是今天介绍的几种常见的魔术方法,当然还有很多的魔术方法,在这就不一一赘述了。算是个人学习笔记分享,如果问题,欢迎提问和建议。