如何在父类的__init__调用的方法中使用子类的属性



我想覆盖继承类中的一些默认类属性,这些属性会影响中间类的功能。例如,在下面的代码片段中,在中间Child的初始化中,我希望对internal_setting的调用依赖于GrandChild设置的_a,以便输出都是that

class Parent():
def __init__(self):
# set a basic parameter
self._a = True

def externally_called_method(self):
# uses correct self._a 
if self._a:
self.externally_set =  "this"
else:
self.externally_set = "that"

class Child(Parent):
def __init__(self):
super().__init__()
self.internal_settings()

def internal_settings(self):
# uses most recent self._a
if self._a:
self.internally_set = "this"
else:
self.internally_set = "that"

class GrandChild(Child):
def __init__(self):
super().__init__()
self._a = False

g = GrandChild()
g.externally_called_method()
print("Internally set: {}".format(g.internally_set))
print("Externally set: {}".format(g.externally_set))
>>> Internally set: this
>>> Externally set: that

中间(Child)类的__init__调用的方法是否可能使用GrandChild类的属性?

我知道我可以让_a成为一个参数,但我不喜欢这样做,因为在实际的程序中,Parent类有大量的属性,可以被子类覆盖。第二个问题是,一般来说,这是否是一种糟糕的方法,即通过继承类的阶梯来促进自定义,其中属性可以根据用例设置。

一旦你运行一个方法,它将运行体贴-如果Parent.__init__被调用初始化参数,它是从Child.__init__调用的,没有办法你可以从GrandChild.__init__改变:它可以,显然,只是运行Child.__init__作为一个单一的调用。

然而,如果你把你的类分解成更多的组件,这是很容易修复的。

如果参数可以是类属性,就像在__init__之外声明它们一样简单,oo的自然继承规则将为您工作:


class Parent():
_a = True
def __init__(self):
# basic parameters are set as class attributes.
...
...

class GrandChild(Child):
_a = False
def __init__(self):

super().__init__()

如果它们不能是直接的类属性(由于需要从运行时输入传递给__init__),您所要做的就是将类的职责分解为更多的方法(可以调用这些方法"槽"),因此,__init__而不是初始化所有参数的责任,然后调用internal_settings-可以将初始化参数的责任委托给另一个方法。这样,你就可以在孙子上重写那个方法:

class Parent():
def __init__(self):
self._set_parameters()
def _set_parameters(self):
self._a = True

def externally_called_method(self):
# uses correct self._a 
if self._a:
self.externally_set =  "this"
else:
self.externally_set = "that"

class Child(Parent):
def __init__(self):
super().__init__()
self.internal_settings()
...

class GrandChild(Child):
def __init__(self):
super().__init__()
def _set_parameters(self):
self._a = False

当然,你的问题比这更复杂——但你所要做的就是把所有的初始化或任务移动到单独的方法中,这样你就可以根据需要替换子类中的任何设置。

最新更新