本文只讨论python2环境下的一些必知相关话题,秉承极简阐述
许多pythoner在编程的过程中可能使用过_new_与_init_方法,但是却没有去理解过它们,今天以前我也一样,但是今天以后我可以说我理解了!
本文所有与类有关的话题中,类都指的是新类
分别有什么功能
__new__是用来创造一个类的实例(constructor),调用时所接收的第一个参数是cls
而__init__是用来初始化一个实例(initializer),调用时所接收的第一个参数是self
调用顺序
先调用new方法然后再调用init方法
原因:既然init是用来初始化一个实例的,那么实例哪里来的呢,当然要先调用new来创建然后才能对这个实例进行初始化。
调用时传参的区别
其实能理解调用顺序的话对于传递的参数就很好理解了:
__new__所接收的第一个参数是cls,因为要创建实例,那么实例是根据什么来创建呢?当然是类了,所以传递cls;
__init__所接收的第一个参数是self,self指的是要初始化的对象,也就是new出来的对象
两者在调用时候的联系
下文将通过重载_new_和_init_来讲解两者在调用时的不同
注意:
__init__中不能有返回值
看下图,我们可以知道一般情况:
在__new__返回一个新创建并且属于该类的实例时当前类的__init__会被调用
看下图我们得到另一种情况:
如果__new__返回的实例不属于当前类,那么当前类的__init__不会被调用;另外,如果__new__不返回任何对象的话也会出现这种情况
一个小练习
通过使用__new__实现单例模式
单例模式是确保一个类只有一个实例,并且这个实例是自己创造的,在系统中用到的都是这个实例
class SingleTon(object):
def __new__(cls, *args, **kwargs):
#每一次实例化的时候,我们都只会返回这同一个instance
if not hasattr(cls, 'instance'):
cls.instance = super(SingleTon, cls).__new__(cls)
return cls.instance
class MyClass(SingleTon):
def __init__(self, val):
self.val = val
def obj_fun(self):
print self.val, 'obj_fun'
if __name__=="__main__":
a = MyClass(1)
b = MyClass(2)
print a is b
print id(a), id(b)
# 类型验证
print type(a) # <class '__main__.MyClass'>
print type(b) # <class '__main__.MyClass'>
运行结果如下:
由以上运行结果中两个实例的id一致可验证实现了单例模式
那么非单例模式会返回什么呢,我们修改MyClass的继承类如下
class MyClass(object):
运行结果如下:
一目了然,我们创建了两个不同的实例,非单例模式