本文旨在澄清 python 里 __new__
vs __init__
和 cls
vs self
的概念。 python
不少初学者会困扰,python的“魔法函数” __new__
有啥用? 跟__init__
有啥区别? 为何有的函数第一个输入变量是self
, 有的倒是cls
? 这有啥区别?函数
好,废话很少说,先看一个例子:code
class A(object): def __new__(cls): print("A.__new__ called") return super(A, cls).__new__(cls) def __init__(self): print("A.__init__ called") A() print('finished')
运行结果为:orm
A.__new__ called A.__init__ called finished
为何结果是这样呢?
由于:__new__
负责建立一个 object;以后 __init__
负责初始化这个 object。it
有点绕是吧,再说具体点:io
当A()
被 call 的时候,__new__
就自动执行了, 它建立了一个object(class的具体实例)并返回这个object,而后__init__
接手这个实例再接着执行。 form
每当__new__
建立并返回一个实例时,__init__
就接手这个实例而后执行,这个实例就是__init__
的第一个输入变量,永远不变的, 默认的self
。 说到这里,self
怎么来的应该很清楚了吧。class
在日常应用中,咱们定义某个class
时几乎不会去写它的__new__
方法,因而当咱们call这个class
时,python会一直往上追溯到有__new__
的父辈class, 一般咱们自定义的class都是object
的子类,因此执行的都是它的__new__
。object
的__new__
建立并返回的这个实例,是裸的。 而后咱们的class
的__init__
再接手这个裸的实例去进一步加工,好比加上各类 self.xxx = xxx
, 或再执行一些别的code, 这个过程就是initialization。注意它和creation的区别,应该说的很清晰了吧。变量
那假如咱们本身定义一个坏了的__new__
, 它没有返回一个实例,这事会发生什么呢?好比:object
class A(object): def __new__(cls): print("A.__new__ called") #return super(A, cls).__new__(cls) def __init__(self): print("A.__init__ called") A()
运行一下,发现结果是:
A.__new__ called finished
哈哈固然啦,__new__
没有返回一个建立好的实例,那么__init__
天然就执行不了了。 上头没有提供食材,厨子就揭不开锅作饭嘛。
这个时候有人会问了,为啥 __init__()
里面是 self
, 而__new__()
里面是cls
呢?
首先,咱们澄清一下概念:
一、self
表示一个具体的实例(instance)
自己。(若是用了@staticmethod
,那么就能够无视这个self,由于staticmethod就能够理解成一个普通的函数)
二、cls
表示这个类(class)
自己。
OK, __init__()
里面的self
已经说清楚了,是刚刚__new__
出炉的一个建立好的实例(object / instance); 那__new__()
里面是cls
又是指哪一个class呢?
简单说来:哪一个class
召唤了__new__
, cls
就默认是哪一个class
。
再看一个例子 (Singleton 单例模式的实现):
class Singleton(object): def __new__(cls, *args, **kw): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) print('\n') print('cls is ', cls) print(type(cls._instance), cls._instance) else: print(' {} already exists'.format(cls._instance)) return cls._instance class Bus(Singleton): def sendData(self,data): pass class BusSon(Bus): def sendData(self,data): pass if __name__ == '__main__': busson1 = BusSon() bus1 = Bus() print('------------------------\n') busson2 = BusSon() bus2 = Bus() print('------------------------\n') Bus.__new__(BusSon) Bus() x = Singleton.__new__(Bus) print(x)