首页 > 代码库 > 奇怪的Pecan class
奇怪的Pecan class
最近弄了一段时间的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)
按如下方式初始化一个Pecan实例
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__呢?
经过实验证明这里返回值p为ExplicitPecan实例,而非Pecan实例。
做个实验:
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实例了。
奇怪的Pecan class
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。