最近弄了一段时间的ironic,终于把它给调通,可以正常使用了。这两天有时间可以把ironic的api发布流程学习一下,ironic-api发布并不像nova-api那样--自己实现api发布流程,而是采用了轻量级框架pecan。所以就学习下pecan,没想到pecan文档网页被墙了,打不开,只好看源码了。这里并非想阐述pecan框架的实现结构,而只是想探讨下Pecan类的继承和实例化,及引出对__new__调用的实验。
先看代码:
class PecanBase(object): class ExplicitPecan(PecanBase): class Pecan(PecanBase): def __new__(cls, *args, **kw): if kw.get('use_context_locals') is False: self = super(Pecan, cls).__new__(<strong>ExplicitPecan</strong>, *args, **kw) print 'use_context_locals' self.__init__(*args, **kw) return self return super(Pecan, cls).__new__(cls)
from pecan import core p=core.Pecan('ironic.api.controllers.root.RootController')这种初始化不会存在什么疑惑,if语句判断结果为不成立,不会执行。直接返回一个Pecan实例。
如下按照这种方式初始化,p会是什么类的实例呢?
p=core.Pecan('ironic.api.controllers.root.RootController',use_context_locals=False)这里传入use_context_locals=False,if判断成立,执行if body。但是这里调用父类的__new__函数很特别,它传入的是ExplicitPecan,而非默认的cls(即Pecan),返回一个ExplicitPecan实例,并调用它的__init__进行初始化。Pecan的__new__函数将返回一个初始化过的ExplicitPecan实例,ExplicitPecan实例没有init_context_local(),那它又怎么继续调用Pecan的__init__呢?
做个实验:
class A(object): def __new__(cls, *args): print "A __new__:", cls return super(A, cls).__new__(cls, *args) def __init__(self, *args): print "A __init__", self super(A, self).__init__(*args) class B(A): def __new__(cls, *args): print "B __new__:", cls return super(B, cls).__new__(cls, *args) def __init__(self, *args): super(B, self).__init__(*args) print "B __init__", self class C(A): def __new__(cls, *args): print "C __new__:", cls return super(C, cls).__new__(<strong>B</strong>, *args) def __init__(self, *args): super(C, self).__init__(*args) print "C __init__", self
In [2]: b=testforInit.B() B __new__: <class 'testforInit.B'> A __new__: <class 'testforInit.B'> A __init__ <testforInit.B object at 0x7fb6cdf70150> B __init__ <testforInit.B object at 0x7fb6cdf70150> In [3]: c=testforInit.C() C __new__: <class 'testforInit.C'> A __new__: <class 'testforInit.B'> In [4]: print b.__class__ <class 'testforInit.B'> In [5]: print c.__class__ <class 'testforInit.B'>这里可以看到,B按照常规方法调用父类的__new__函数,函数的执行顺序和结果正常。但C调用父类的__new__函数时,传入的是B,而非C。从结果可以看到这样只执行了C和A的__new__函数,返回的是一个B的实例。而A、B、C的__init__函数都未被调用。这里也可以解释了,为什么要在Pecan.__new__的if里面调用ExplicitPecan.__init__函数,否则返回的就是一个未初始化的ExplicitPecan实例了。
原文地址:http://blog.csdn.net/xuriwuyun/article/details/40857617