python 与父 类 的多重继承有不同 __init__()
python multi inheritance with parent classes have different __init__()
这里的B
和C
都是从A
派生出来的,但是__init__()
参数不同。我的问题是如何在这里写correct/elegant代码来初始化下面例子中的self.a,self.b,self.c1,self.c2?
也许另一个问题是——在 __init()__
函数中进行此变量设置是一个好的编码习惯还是使用更简单的 __init__()
函数更好,并为每个 [=] 执行 set()
函数27=] 之后,这似乎不像在 __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 中的多重继承要求所有 classes 协作才能使其工作。在这种情况下,您可以通过让每个 class 中的 __init__
方法接受任意 **kwargs
并在它们调用 super().__init__
.
时传递它们来使它们合作
对于您的示例 class 层次结构,您可以这样做:
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()
通话:
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!
如果某些父 classes 不将参数(以其原始形式)保存为属性,那么接受并传递某些参数很重要,但您需要这些值。您还可以使用这种代码风格为某些参数传递修改后的值(例如 super(D, self).__init__(a=a, b=b, c1=2*c1, c2=5*c2, **kwargs)
)。
这种具有不同参数的协作多重继承几乎不可能使用位置参数来实现。但是,对于关键字参数,调用中名称和值的顺序并不重要,因此很容易同时传递命名参数和 **kwargs
而不会造成任何破坏。使用 *args
效果不佳(尽管 Python 3 的最新版本在如何使用 *args
调用函数方面更加灵活,例如允许在单个调用中进行多次解包:f(*foo, bar, *baz)
).
如果您使用的是 Python 3(我假设不是,因为您明确将参数传递给 super
),您可以将参数设为协作函数 "keyword-only",这将防止用户混淆并尝试使用位置参数调用您的方法。只需在参数列表中的其他命名参数之前放置一个 *
:def __init__(self, *, c1, c2, **kwargs):
.
这里的B
和C
都是从A
派生出来的,但是__init__()
参数不同。我的问题是如何在这里写correct/elegant代码来初始化下面例子中的self.a,self.b,self.c1,self.c2?
也许另一个问题是——在 __init()__
函数中进行此变量设置是一个好的编码习惯还是使用更简单的 __init__()
函数更好,并为每个 [=] 执行 set()
函数27=] 之后,这似乎不像在 __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 中的多重继承要求所有 classes 协作才能使其工作。在这种情况下,您可以通过让每个 class 中的 __init__
方法接受任意 **kwargs
并在它们调用 super().__init__
.
对于您的示例 class 层次结构,您可以这样做:
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()
通话:
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!
如果某些父 classes 不将参数(以其原始形式)保存为属性,那么接受并传递某些参数很重要,但您需要这些值。您还可以使用这种代码风格为某些参数传递修改后的值(例如 super(D, self).__init__(a=a, b=b, c1=2*c1, c2=5*c2, **kwargs)
)。
这种具有不同参数的协作多重继承几乎不可能使用位置参数来实现。但是,对于关键字参数,调用中名称和值的顺序并不重要,因此很容易同时传递命名参数和 **kwargs
而不会造成任何破坏。使用 *args
效果不佳(尽管 Python 3 的最新版本在如何使用 *args
调用函数方面更加灵活,例如允许在单个调用中进行多次解包:f(*foo, bar, *baz)
).
如果您使用的是 Python 3(我假设不是,因为您明确将参数传递给 super
),您可以将参数设为协作函数 "keyword-only",这将防止用户混淆并尝试使用位置参数调用您的方法。只需在参数列表中的其他命名参数之前放置一个 *
:def __init__(self, *, c1, c2, **kwargs):
.