最近弄了一段时间的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__", selfIn [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