Python:继承超类__init__

Ada*_*tan 58 python inheritance constructor init

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

def BaseClass(object):
    def __init__(self, a, b, c, d, e, f, ...):
        self._a=a+b
        self._b=b if b else a
        ...
Run Code Online (Sandbox Code Playgroud)

所有继承类都应该运行__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, ...)

...
Run Code Online (Sandbox Code Playgroud)

什么是Pythonic自动调用超类的方法__init__

小智 49

super(SubClass, self).__init__(...)
Run Code Online (Sandbox Code Playgroud)

如果它有助于解决你的可变噩梦,请考虑使用*args和**kw.

  • 同样在Python 3中,`super().__ init __(...)`将起作用. (13认同)
  • @Adam Matan不,没有.请参阅此处原因:[为什么不自动调用Python的超类__init__方法?](http://stackoverflow.com/questions/3782827/why-arent-pythons-superclass-init-methods-automatically-invoked) (4认同)
  • @CatPlusPlus对不起,我有一个非常愚蠢的问题。在Python 3中,如何使用省略号来填充__init __()?我不断出错。当你们使用“ ...”时,您是在代码中真正表示省略号还是只是为了节省键入? (2认同)

Rya*_* Ye 32

你必须明确地写它,但另一方面,如果你有很多args,你应该使用*args作为位置args和**kwargs作为关键字args.

class SubClass(BaseClass):
    def __init__(self, *args, **kwargs):
        super(SubClass, self).__init__(*args, **kwargs)
        # SubClass initialization code
Run Code Online (Sandbox Code Playgroud)

您可以使用的另一种技术是最小化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
        ...
Run Code Online (Sandbox Code Playgroud)

  • 改进:kwargs.get('a', defaultvaluehere) 而不是 kwargs.get('a') (2认同)

pil*_*her 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 '''
Run Code Online (Sandbox Code Playgroud)

由于__new__()始终自动调用,因此派生类中不需要进一步的工作.


Rob*_*wie 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
Run Code Online (Sandbox Code Playgroud)


小智 8

也许更清晰的实现是在派生类中使用** 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
Run Code Online (Sandbox Code Playgroud)

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

  • 所有解决方案都应该像这样。 (2认同)