我有一个带有很多__init__
个参数的基类:
def BaseClass(object):
def __init__(self, a, b, c, d, e, f, ...):
self._a=a+b
self._b=b if b else a
...
所有继承类都应该运行基类的__init__
方法。
我可以在每个继承类中编写一个__init__()
方法来调用超类__init__
,但这将是一个严重的代码重复:
def A(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
def B(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
def C(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
...
自动调用超类__init__
的最Pythonic方法是什么?
答案 0 :(得分:48)
super(SubClass, self).__init__(...)
如果它有助于解决你的可变噩梦,请考虑使用* args和** kw。
答案 1 :(得分:32)
你必须明确地写它,但另一方面,如果你有很多args,你应该使用* args作为位置args和** kwargs作为关键字args。
class SubClass(BaseClass):
def __init__(self, *args, **kwargs):
super(SubClass, self).__init__(*args, **kwargs)
# SubClass initialization code
您可以使用的另一种技术是最小化 init 中的代码,然后在 init 函数结束时调用另一个自定义函数。然后在子类中,您只需要覆盖自定义函数
class BaseClass(object):
def __init__(self, *args, **kwargs):
# initialization code
self._a = kwargs.get('a')
...
# custom code for subclass to override
self.load()
def load():
pass
class SubClass(BaseClass)
def load():
# SubClass initialization code
...
答案 2 :(得分:18)
如果派生类没有实现超出基类__init__()
已经执行的任何操作,那么只需省略派生类__init__()
方法 - 然后自动调用基类__init__()
。
如果,OTOH,你的派生类在他们的__init__()
中添加了一些额外的工作,并且你不希望他们明确地调用他们的基类__init__()
,你可以这样做:
class BaseClass(object):
def __new__(cls, a, b, c, d, e, f, ...):
new = object.__new__(cls)
new._a=a+b
new._b=b if b else a
...
return new
class A(BaseClass):
''' no __init__() at all here '''
class B(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
''' do stuff with init params specific to B objects '''
由于始终自动调用__new__()
,因此派生类中不需要进一步的工作。
答案 3 :(得分:14)
除非你在子类__init__()
方法中做了一些有用的事情,否则你不必覆盖它。
def BaseClass(object):
def __init__(self, a, b, c, d, e, f, ...):
self._a=a+b
self._b=b if b else a
...
def A(BaseClass):
def some_other_method(self):
pass
def B(BaseClass):
pass
答案 4 :(得分:4)
对于您的案例,更清晰的实现可能是在您的派生类中使用** kwargs 结合新添加的参数,如下所示:
class Parent:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
class Child(Parent):
def __init__(self, d, **kwargs):
super(Child, self).__init__(**kwargs)
self.d = d
通过这种方法可以避免代码重复,但保留派生类中隐式添加的参数。
答案 5 :(得分:2)
在2.6及更低版本中从基类继承init,没有超级函数,你可以继承以下方式:
class NewClass():
def __init__():
BaseClass.__init__(self, *args)
答案 6 :(得分:0)
添加Pythonic实现。假设您想要传入所有属性,可以使用下面的代码。 (如果你想要一个子集,也可以保留/删除特定的kwargs键。)
def A(BaseClass):
def __init__(self, *args, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
base = BaseClass(...)
new = A( **base.__dict__ )