关于继承:Python:继承超类__init__

Python: Inherit the superclass __init__

我有一个包含很多__init__参数的基类:

1
2
3
4
5
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__()方法,但这将是一个严重的代码重复:

1
2
3
4
5
6
7
8
9
10
11
12
13
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__的最Python的方法是什么?


1
super(SubClass, self).__init__(...)

考虑使用*args和**kw,如果它有助于解决变量噩梦。


您必须显式地编写它,但另一方面,如果您有很多参数,您可能应该使用*args作为位置参数,使用**kwargs作为关键字参数。

1
2
3
4
class SubClass(BaseClass):
    def __init__(self, *args, **kwargs):
        super(SubClass, self).__init__(*args, **kwargs)
        # SubClass initialization code

您可以使用的另一种技术是最小化init中的代码,然后在init函数结束时调用另一个自定义函数。然后在子类中,只需要重写自定义函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
        ...


如果派生类没有实现任何超出基类__init__()已经实现的功能,只需省略派生类__init__()方法-然后自动调用基类__init__()

如果您的派生类在它们的__init__()中添加了一些额外的工作,并且您不希望它们显式地调用它们的基类__init__(),那么您可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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__()总是自动调用的,因此派生类中不需要进一步的工作。


除非您在子类__init__()方法中做了一些有用的事情,否则您不必重写它。

1
2
3
4
5
6
7
8
9
10
11
12
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


也许更清晰的实现是在派生类中使用**Kwargs和新添加的参数,如:

1
2
3
4
5
6
7
8
9
10
11
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

通过此方法,可以避免代码重复,但保留派生类中隐式添加的参数。


在2.6及更低版本中,要从基类继承init,没有super函数,可以通过以下方式继承:

1
2
3
class NewClass():
     def __init__():
         BaseClass.__init__(self, *args)


添加pythonic实现。假设您希望传入所有属性,则可以使用下面的代码。(如果需要子集,还可以保留/删除特定的Kwargs键)。

1
2
3
4
5
6
7
def A(BaseClass):
    def __init__(self, *args, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

base = BaseClass(...)
new = A( **base.__dict__ )