[英]Partially initializing base class
想不到一个更好的问题标题。 随时编辑。 我有一个由许多类继承的基类(而基类又可能有更多的子类)。 对于每个类,我都有执行初始化后所需的一系列操作。 序列封装在函数runme()
,该函数执行一系列对象方法调用
class myBase(object):
def __init__(self,neg,op,value):
self.neg = neg
self.op = op
self.value = value
#Process
self.runme()
def runme(self):
self.preprocess()
self.evaluate()
self.postprocess()
def preprocess(self):
pass
def evaluate(self):
pass
def postprocess(self):
pass
子类必须接受与基相同的属性(以及任何其他属性)。 它们都将超越三个功能- preprocess
, evaluate
和postprocess
class childA(myBase):
def __init__(self,neg,op,value,ad1):
super(childA,self).__init__(neg,op,value)
self.ad1 = ad1
#Must call runme() here again??
runme()
def evaluate():
#Something using self.ad1
blah = self.ad1+self.value
我看到它的方式,它产生了一个问题- childA
调用基__init__
第一,它调用runme()
这反过来将调用evaluate
。 由于过孩子的游乐设施evaluate
,孩子的定义, evaluate
被执行,但self.ad1
尚未实例化,这将引发一个AttributeError
我可以从myBase中删除self.runme()
,问题可能会消失,但是我可以进一步将childA
childAA
为childAA
class childAA(childA):
def __init__(self,neg,op,value,ad1):
super(childAA,self).__init__(neg,op,value,ad1)
self.runme()
问题会再次出现。 我无法从childA的__init__
删除runme()
,因为childA
和childAA
对象都可以形成(并且需要处理)
当前,作为一种解决方法,我不在__init__
调用runme()
,而是在初始化后从调用程序中对其进行调用。
obja=childA(foo,bar,baz,ad1)
obja.runme()
一个更简单的替代方法是调用super()
在孩子的结束__init__
,但这并不似乎是正确的
另一种方法是-告诉基类将runme()的调用推迟到子类。 这可能吗? 在myBase中说
def __init__(self,neg,op,value):
self.neg = neg
self.op = op
self.value = value
#Process
if some_condition which checks if this is being called by a derived class:
self.runme()
如果这些是解决问题的最佳方法,那该怎么办? 或者,这是一个常见问题吗?还有其他建议的解决方案吗?
编辑
发布了两个答案(并删除了),它们的最佳方法似乎是将runme()
调用留在基类中,然后在孩子的__init__
末尾调用super()
。
class myBase(object):
def __init__(self,neg,op,value):
self.neg = neg
self.op = op
self.value = value
#Process
self.runme()
class childA(myBase):
def __init__(self,neg,op,value,ad1):
self.ad1 = ad1
super(childA,self).__init__(neg,op,value)
如果您需要依赖现有值的值,
class childA(myBase):
def __init__(self,neg,op,value,ad1):
self.ad1 = ad1
self.internal_value = self.value #Not yet initialized!!
super(childA,self).__init__(neg,op,value)
该代码可以放在preprocess()
或其他在runme()
首先调用的函数中
def preprocess(self):
self.internal_value = value
#Rest of the stuff
如果孩子的__init__
需要部分初始化的对象才能继续进行,则最后调用super()
确实无法正常工作。 如果是这样的话,你可以打电话给runme
的形式__new__
在myBase
:
class myBase(object):
def __new__(cls, *args, **kwargs):
obj = super(myBase, cls).__new__(cls)
obj.__init__(*args, **kwargs)
obj.runme()
def __init__(self, a):
print 'myBase init'
self.list = ['myBase', a]
def runme(self):
print 'myBase:', self.list
class ChildA(myBase):
def __init__(self, a, b):
print 'ChildA init'
super(ChildA, self).__init__(a)
self.list.extend(['ChildA', b])
def runme(self):
print 'ChildA:', self.list
class ChildAA(ChildA):
def __init__(self, a, b, c):
print 'ChildAA init'
super(ChildAA, self).__init__(a, b)
self.list.extend(['ChildAA', c])
def runme(self):
print 'ChildAA:', self.list
您可以根据初始化过程的要求在各种__init__
函数中订购代码,并且在__init__
完成后,始终会调用正确的runme
函数:
>>> ChildA(1, 2)
ChildA init
myBase init
ChildA: ['myBase', 1, 'ChildA', 2]
>>> ChildAA(1, 2, 3)
ChildAA init
ChildA init
myBase init
ChildAA: ['myBase', 1, 'ChildA', 2, 'ChildAA', 3]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.