python多重继承使用super将参数传递给构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34884567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 15:40:49  来源:igfitidea点击:

python multiple inheritance passing arguments to constructors using super

pythonmultiple-inheritancesuperdiamond-problem

提问by Lin

Consider the following snippet of python code

考虑以下python代码片段

class A(object):
    def __init__(self, a):
        self.a = a

class B(A):
    def __init__(self, a, b):
        super(B, self).__init__(a)
        self.b = b

class C(A):
    def __init__(self, a, c):
        super(C, self).__init__(a)
        self.c = c

class D(B, C):
    def __init__(self, a, b, c, d):
        #super(D,self).__init__(a, b, c) ???
        self.d = d

I am wondering how can I pass a, band cto corresponding base classes' constructors.

我想知道如何将a,b和传递c给相应的基类的构造函数。

采纳答案by shx2

Well, when dealing with multiple inheritance in general, your base classes (unfortunately) should be designed for multiple inheritance. Classes Band Cin your example aren't, and thus you couldn't find a proper way to apply superin D.

好吧,一般来说,在处理多重继承时,您的基类(不幸的是)应该设计为多重继承。类BC在您的示例中不是,因此您找不到superD.

One of the common ways of designing your base classes for multiple inheritance, is for the middle-level base classes to accept extra args in their __init__method, which they are not intending to use, and pass them along to their supercall.

为多重继承设计基类的常用方法之一是让中间层基类在其__init__方法中接受额外的参数,它们不打算使用,并将它们传递给super调用。

Here's one way to do it in python:

这是在python中执行此操作的一种方法:

class A(object):
    def __init__(self,a):
        self.a=a

class B(A):
    def __init__(self,b,**kw):
        self.b=b
        super(B,self).__init__(**kw)

 class C(A):
    def __init__(self,c,**kw):
        self.c=c
        super(C,self).__init__(**kw)

class D(B,C):
    def __init__(self,a,b,c,d):
        super(D,self).__init__(a=a,b=b,c=c)
        self.d=d

This can be viewed as disappointing, but that's just the way it is.

这可以被视为令人失望,但事实就是如此。

回答by Brendan Abel

Unfortunately, there is no way to make this work using super()without changing the Base classes. Any call to the constructors for Bor Cis going to try and call the next class in the Method Resolution Order, which will always be Bor Cinstead of the Aclass that the Band Cclass constructors assume.

不幸的是,没有办法在super()不改变基类的情况下使用它。该构造的任何呼吁BC打算尝试拨打下一个类的方法解析顺序,这将永远是BC代替A类的BC类的构造函数承担。

The alternative is to call the constructors explicitly without the use of super()in each class.

另一种方法是显式调用构造函数,而不super()在每个类中使用。

class A(object):
    def __init__(self, a):
        object.__init__()
        self.a = a

class B(A):
    def __init__(self, a, b):
        A.__init__(self, a)
        self.b = b

class C(object):
    def __init__(self, a, c):
        A.__init__(self, a)
        self.c = c

class D(B, C):
    def __init__(self, a, b, c, d):
        B.__init__(self, a, b)
        C.__init__(self, a, c)
        self.d = d 

There is still a downside here as the Aconstructor would be called twice, which doesn't really have much of an effect in this example, but can cause issues in more complex constructors. You can include a check to prevent the constructor from running more than once.

这里仍然有一个缺点,因为A构造函数会被调用两次,这在本示例中并没有太大影响,但可能会导致更复杂的构造函数出现问题。您可以包含一个检查以防止构造函数多次运行。

class A(object):
    def __init__(self, a):
        if hasattr(self, 'a'):
            return
        # Normal constructor.

Some would call this a shortcoming of super(), and it is in some sense, but it's also just a shortcoming in multiple inheritance in general. Diamond inheritance patterns are often prone to errors. And a lot of the workarounds for them lead to even more confusing and error-prone code. Sometimes, the best answer is to try and refactor your code to use less multiple inheritance.

有些人会称这是 的缺点super(),从某种意义上说,它也只是多重继承的缺点。菱形继承模式通常容易出错。他们的许多变通方法会导致代码更加混乱和容易出错。有时,最好的答案是尝试重构您的代码以使用更少的多重继承。