什么是魔术方法
Python中,所有以两个下划线开头并以两个下划线结尾的方法,都统称“Magic Method”,中文称为魔术方法或魔法方法。魔术方法会在对类的某个操作时自动调用,而不需要编码人员操作调用。
魔术方法都是python内部定义的,自己是不可以定义__plscript__
这类双下划线包裹的方法的。
常用的魔术方法
__init__
通常把__init__
方法称为构造函数或初始化方法,只要实例化一个对象,这个方法就会在对象被初始化时自动调用。初始化对象时是可以传入参数的,这些参数会自动传入__init__
方法中,可以通过重写这个方法来自定义对象的初始化操作。
class MyClass(object):
def __init__(self):
print("init 方法")
def myfunc(self):
print("func")
MyClass()
执行上面的代码
init 方法
上面代码只是初始化了MyClass
并没有调用任何方法,但执行结果,输出了__init__
方法的内容。这里就说明了,在进行类初始化时会自动执行__init__
方法,这里在MyClass
中进行了定义。而实际上MyClass
的父类object
是定义了__init__
方法的。(所有类都继承于object
类,可以省略不写)
自己定义的类中,定义了__init__
即相当于重写了父类的__init__
方法。若自已定义的类中没有,则执行父类的__init__
方法。
在定义__init__
时还可以传递参数,进行初始化。
class MyClass(object):
def __init__(self, name, age):
print("init 方法")
self.name = name
self.age = age
print("{},{}".format(name, age))
def myfunc(self):
print("func")
MyClass('laobai', 18)
执行代码
init 方法
laobai,18
__new__
__new__
是一个由object
类提供的内置的静态方法,它的作用是调用类时创建对象及分配内存空间。也就是在类进行调用时,先通过__new__
创建并返回对象,再执行__init__
进行对象的初始化。
class MyClass(object):
def __init__(self):
print("init 方法")
def myfunc(self):
print("func")
obj = MyClass()
print(obj)
执行结果:
init 方法
<__main__.MyClass object at 0x10317f070>
这个例子中没有__new__
方法,会直接调用父类的__new__
创建对象分配内存空间并返回对象,再执行自己定义的__init__
方法。
下面自己定义一个__new__
方法
class MyClass(object):
def __new__(cls):
print("new 方法")
def __init__(self):
print("init 方法")
def myfunc(self):
print("func")
obj = MyClass()
print(obj)
执行代码
new 方法
None
结果只执行了__new__
方法,没有执行__init__
方法,且实例化的对象结果为None
。这是因为__new__
方法还需要返回创建的对象,有了对象,__init__
才能进行初始化。
class MyClass(object):
def __new__(cls):
print("new 方法")
return super().__new__(cls)
def __init__(self):
print("init 方法")
def myfunc(self):
print("func")
obj = MyClass()
print(obj)
再次执行
new 方法
init 方法
<__main__.MyClass object at 0x105080eb0>
即先执行自定义的__new__
方法并返回父类的__new__
进行对象的创建,然后执行自定义的__init__
方法,最后打印输出对象。
__new__
方法很少需要进行重写,若重写,返回父类的__new__
语法比较固定return super().__new__(cls)
单例模式
单例模式是通过__new__
方法的一个特殊应用。通常情况下,一个类可以实例化无限多个对象,而单例模式,就是这个类只能实例化一个对象。大概思路就是创建对象(调用__new__
)时,判断是否创建过对象,没有创建过就返回object
类的__new__
方法,若已经创建过对象,那么返回前一次创建的对象。保证创建的对象只有一个。
通常情况下:
class MyClass:
def __new__(cls, *args, **kwargs):
return super().__new__(cls)
a = MyClass()
b = MyClass()
c = MyClass()
print(a, b, c)
执行
<__main__.MyClass object at 0x1013bd0a0> <__main__.MyClass object at 0x1013bdd90> <__main__.MyClass object at 0x1013bd580>
可以看到,3个对象的内存地址不一样,即完全不同的3个对象。
单例模式:
class MyClass:
__instance = None
def __new__(cls, *args, **kwargs):
# 判断类是否实例化过对象
if not cls.__instance:
cls.__instance = super().__new__(cls)
return cls.__instance
a = MyClass()
b = MyClass()
c = MyClass()
print(a, b, c)
执行
<__main__.MyClass object at 0x10e364f10> <__main__.MyClass object at 0x10e364f10> <__main__.MyClass object at 0x10e364f10>
可以看到,3个对象的内存地址都是0x10e364f10,即为一个对象。