此处B
和C
均来自A
,但参数不同__init__()
。我的问题是如何在这里编写正确/优雅的代码来初始化self.a,self.b,self.c1,self.c2在下面的例子中?
也许另一个问题是 - 在__init()__
函数中进行此变量设置是一种很好的编码实践,还是使用更简单的__init__()
函数更好,并且稍后为每个类执行set()
函数,这似乎不像在__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)
答案 0 :(得分:1)
Python中的多重继承要求所有类合作才能使其工作。在这种情况下,您可以通过让每个类中的__init__
方法接受任意**kwargs
并在他们调用super().__init__
时将其传递来使他们合作。
对于您的示例类层次结构,您可以执行以下操作:
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
等),您可以将它们作为命名参数并仍然在{{{ 1}}来电:
super()
如果某些父类不将参数(以其原始形式)保存为属性,则接受并传递一些参数非常重要,但您需要这些值。您还可以使用此样式的代码来传递某些参数的修改值(例如,使用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!
)。
这种具有不同参数的协作多重继承几乎不可能使用位置参数来完成工作。但是,使用关键字参数,调用中的名称和值的顺序并不重要,因此很容易同时传递命名参数和super(D, self).__init__(a=a, b=b, c1=2*c1, c2=5*c2, **kwargs)
而没有任何破坏。使用**kwargs
也不起作用(尽管最新版本的Python 3更灵活地使用*args
调用函数,例如在一次调用中允许多个解包:{{1 }})。
如果您使用的是Python 3(我假设没有,因为您明确地将参数传递给*args
),您可以为您的协作功能提供参数" keyword-只有",这会阻止用户混淆并尝试使用位置参数调用您的方法。只需在参数列表中放置一个裸f(*foo, bar, *baz)
,然后再放入其他命名参数:super
。