自定义 __new__() 方法通常并不经常使用,并且容易与 __init__() 相混淆。实际上这两个方法也确实类似,好比他们都是在建立类的实例时会被默认调用的方法,并且建立实例时传入的参数也都会传到这两个方法里。但他们也有很重要的区别,好比对 __new__() 的调用比 __init__() 要早,__new__() 有返回值,__init__() 木有。python
来理一下建立类的实例的过程,即解释器处理 foo = MyClass() 这条语句的步骤的话,大约是这样的(可能并不彻底准确):shell
即,真正完成构造实例工做的是 __new__() 方法,调用它须要一个默认参数 cls,就是将要返回的这个实例所属的类(MyClass)。通常状况下由于 __new__() 极少被覆盖,最终调用的都是 object.__new__()。这个时候咱们的实例已经被建立了,就能够当作 self 参数传给 __init__() 了,__init__() 作的工做其实仅是初始化一些属性值之类的,与严格意义下的“构造”实例无关。express
这里拿出 __new__() 来讲主要是昨晚看到一道题,说是如何用 Python 实现单例模式,就是某个类同时只容许存在一个实例的意思。比较直接的想法应该是在类属性里添加一个布尔开关(好比就叫 cer 好了),建立实例时检查 cer 的值,True 就容许建立,False 就引起异常。那么这个检查的过程若是安装在 __init__() 里确定是不行的,由于那时实例已经被建立出来了,因此正确的检查位置应该是 __new__() 里面。第二点,cer 这个开关还应该在第一个实例被删除时自动打回到 True 上,因此还须要覆盖 __del__() 方法:函数
class Singleton(object): def __new__(cls): if cls.cer: cls.cer = False return super().__new__(cls) else:raise TypeError('[%s] could be instantiated only once!'%cls.__name__) cer = True def __del__(self): self.__class__.cer = True
运行以下:ui
>>> a = Singleton() >>> a <__main__.Singleton object at 0x0000000009CAC630> >>> b = Singleton() Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> b = Singleton() File "C:\Users\July\Desktop\test.py", line 8, in __new__ else:raise TypeError('[%s] could be instantiated only once!'%cls.__name__) TypeError: [Singleton] could be instantiated only once! >>> b Traceback (most recent call last): File "<pyshell#3>", line 1, in <module> b NameError: name 'b' is not defined >>> del a >>> b = Singleton() >>> b <__main__.Singleton object at 0x0000000009CAC358>
看起来很是好,不过上面的运行结果其实被删减过,实际上颇有可能:del a 以后也建立不出 b 实例,即那时 Singleton.cer 的值仍为 False。为何呢,这就要从 Python 的垃圾回收器提及了。code
Python 靠引用计数的机制来运行垃圾回收器,因此 del a 这条语句作的事情其实仅仅是将 a 所指向的实例的引用数 -1(固然 a 这个名字也被删掉了),实例的 __del__() 方法不必定会获得执行(由于不排除还有其余的引用指向该实例)。只有当该实例的引用计数减到 0 的时候,垃圾回收器才会来处理它,并调用 __del__() 方法。不过即便像上面的例子那样,实例只有 a 这一个引用,而且咱们也删掉了这个引用,回收器也是不必定会当即回收掉该实例的。你极可能须要“等一会”。。。orm
若是不想等的话,则能够手动运行一次回收器。回收器有一个名为 gc 的模块接口,运行 gc.collect() 函数就能够手动回收,因此上面例子的完美运行结果实际上是这样子的:对象
>>> a = Singleton() >>> a <__main__.Singleton object at 0x0000000009CAC630> >>> b = Singleton() Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> b = Singleton() File "C:\Users\July\Desktop\test.py", line 8, in __new__ else:raise TypeError('[%s] could be instantiated only once!'%cls.__name__) TypeError: [Singleton] could be instantiated only once! >>> b Traceback (most recent call last): File "<pyshell#3>", line 1, in <module> b NameError: name 'b' is not defined >>> del a >>> Singleton.cer False >>> import gc >>> gc.collect() 0 >>> Singleton.cer True >>> b = Singleton() >>> b <__main__.Singleton object at 0x0000000009CAC358>
能够看到这个 object.__del__() 方法并不怎么靠谱,因此通常仍是能不用就不用吧,或者至少知道他们可能不会被当即调用,又或者你非要把 gc.collect() 写进 __new__() 里也行。接口
在子类中覆盖父类的方法,添加一些代码而后再把父类的同名方法调用起来是一种满典型的用法,因此这里 super() 出现的机会也多。通常咱们想要获得一个绑定的父类,都是这样调用 super:ci
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)
好比:
class P(object): def __init__(self): print('calling __init__ of P') class C(P): def __init__(self): return super(C,self).__init__()
子类的 C 里面调用父类 P 的 __init__() 方法(绑定的),就给 super() 函数传了 C 和 C 的实例 self 两个参数表示绑定到 self 上的 P 类。这里也能够用 __class__ 、self.__class__ 或者 type(self) 来代替直接给出当前类的名字 C。
不过由于这种使用 super() 的方式太典型了,因此在 Python3 里能够无参数使用 super() 函数,效果和传两个参数同样:
super() -> same as super(__class__, <first argument>)
这里 <first argument>指代上面的 obj 或者 type2(或者说 self 和 cls),都是可绑定的对象。这也就是最上面的代码没有给 super() 传参数也能够运行的缘由。至于为何最开始的例子里 super().__new__(cls)还给传了个 cls 参数,这是由于 __new__ 方法是静态方法,不能像 super().__init__() 同样由于 super 对象已经绑定了 self 就不给 __init__() 传 self 了。
另外若是不须要绑定,能够只给 super() 传一个参数:
super(type) -> unbound super object
最后要说的是调用父类方法时的语句,能够看到上面的两个例子无论父类方法有没有返回值(__new__ 或 __init__),都使用 return 来调用。这样的好处在于不用去关心该方法到底有没有返回值,就算没有,return expression 的 expression 也同样会被执行,而后 return 一个 None,这显然没什么坏处。