带有父类的python多继承具有不同的__init __() [英] python multi inheritance with parent classes have different __init__()

查看:182
本文介绍了带有父类的python多继承具有不同的__init __()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

BC均来自A,但具有不同的__init__()参数.我的问题是在下面的示例中,如何在此处编写正确/优雅的代码来初始化self.a,self.b,self.c1,self.c2? 也许另一个问题是-在__init()__函数中进行此变量设置是一种好的编码实践,还是最好使用更简单的__init__()函数,并在以后为每个类都使用set()函数,这似乎并不那么简单只是在__init()__中做到这一点?

Here both B and C are derived from A, but with different __init__() parameters. My question is how to write the correct/elegant code here to initialize self.a,self.b,self.c1,self.c2 in the following example? Maybe another question is--is it a good coding practice to do this variable setting in __init()__ function or it is better to use simpler __init__() function, and do set() function for each class later, which seems not as simple as to just do it in __init()__?

class A(object):
    __init__(self,a):
        self.a=a
class B(A):
    __init__(self,a,b):
        super(B,self).__init__(a)
        self.b=b
class C(A):
    __init__(self,a,c1,c2):
        super(C,self).__init__(a)
        self.c1=c1
        self.c2=c2

class D(B,C)
    __init__(self,a,b,c1,c2,d):
        #how to write the correct/elegant code here to initialize self.a,self.b,self.c1,self.c2?
        #can I use super(D,self) something?
        self.d=d
        self.dd=self.a+self.b+2*self.c1+5*self.c2+3*self.d

d=D(1,2,3,4,5)   

推荐答案

Python中的多重继承要求所有类进行协作才能使其正常工作.在这种情况下,您可以通过让每个类中的__init__方法接受任意**kwargs并在调用super().__init__时将它们传递给它们来使它们合作.

Multiple inheritance in Python requires that all the classes cooperate to make it work. In this case, you can make them cooperate by having the __init__ method in each class accept arbitrary **kwargs and pass them on when they call super().__init__.

对于示例类层次结构,您可以执行以下操作:

For your example class hierarchy, you could do something like this:

class A(object):
    __init__(self,a):  # Don't accept **kwargs here! Any extra arguments are an error!
        self.a=a

class B(A):
    __init__(self, b, **kwargs):  # only name the arg we care about (the rest go in **kwargs)
        super(B, self).__init__(**kwargs)  # pass on the other keyword args
        self.b=b

class C(A):
    __init__(self, c1, c2, **kwargs):
        super(C,self).__init__(**kwargs)
        self.c1=c1
        self.c2=c2

class D(B,C)
    __init__(self, d, **kwargs):
        super(D,self).__init__(**kwargs)
        self.d=d
        self.dd=self.a+self.b+2*self.c1+5*self.c2+3*self.d

请注意,如果希望D直接使用参数值(而不是使用self.a等),则既可以将它们用作命名参数,又可以在super()调用中继续传递它们: /p>

Note that if you wanted D to use the argument values directly (rather than using self.a, etc.), you could both take them as named arguments and still pass them on in the super() call:

class D(B,C)
    __init__(self,a, b, c1, c2, d, **kwargs): # **kwargs in case there's further inheritance
        super(D,self).__init__(a=a, b=b, c1=c1, c2=c2, **kwargs)
        self.d = d
        self.dd = a + b + 2 * c1 + 5 * c2 + 3 * d   # no `self` needed in this expression!

如果某些父类没有将参数(以其原始形式)另存为属性,则接受并传递一些arg很重要,但是您需要这些值.您还可以使用这种样式的代码来传递某些参数的修改值(例如,使用super(D, self).__init__(a=a, b=b, c1=2*c1, c2=5*c2, **kwargs)).

Accepting and passing on some args is important if some of the parent classes don't save the arguments (in their original form) as attributes, but you need those values. You can also use this style of code to pass on modified values for some of the arguments (e.g. with super(D, self).__init__(a=a, b=b, c1=2*c1, c2=5*c2, **kwargs)).

这种使用可变参数的协作式多重继承几乎不可能使用位置参数进行工作.但是,对于关键字参数,调用中名称和值的顺序无关紧要,因此可以轻松地同时传递命名参数和**kwargs而不会中断任何内容.使用*args效果不佳(尽管Python 3的最新版本在如何使用*args调用函数方面更为灵活,例如允许在一个调用中多次解压缩:f(*foo, bar, *baz)).

This kind of collaborative multiple inheritance with varying arguments is almost impossible to make work using positional arguments. With keyword arguments though, the order of the names and values in a call doesn't matter, so it's easy to pass on named arguments and **kwargs at the same time without anything breaking. Using *args doesn't work as well (though recent versions of Python 3 are more flexible about how you can call functions with *args, such as allowing multiple unpackings in a single call: f(*foo, bar, *baz)).

如果您使用的是Python 3(我假设不是,因为您已将参数明确传递给super),则可以将协作函数的参数设为仅关键字",这将阻止用户获取非常混乱,并尝试使用位置参数来调用您的方法.只需在参数列表中的其他命名参数之前添加一个空的*:def __init__(self, *, c1, c2, **kwargs):.

If you were using Python 3 (I'm assuming not, since you're explicitly passing arguments to super), you could make the arguments to your collaborative functions "keyword-only", which would prevent users from getting very mixed up and trying to call your methods with positional arguments. Just put a bare * in the argument list before the other named arguments: def __init__(self, *, c1, c2, **kwargs):.

这篇关于带有父类的python多继承具有不同的__init __()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆