我试图理解Python中的MRO。虽然这里有各种各样的帖子,但我并没有特别得到我想要的东西。考虑从BaseClass
派生的两个类A
和{
class BaseClass(object):
def __init__(self):
print "I am the base class"
class A(BaseClass):
def __init__(self, something, anotherthing):
super(A, self).__init__()
self.something = something
self.anotherthing = anotherthing
def methodsA(self):
...
class B(BaseClass):
def __init__(self, someOtherThing):
super(B, self).__init__()
self.someOtherThing = someOtherThing
def methodsB(self):
...
问题是,如果我需要从A
和B
派生第三个类C
,如果必须的话,如何初始化{B
或{
上面的实现给了我一个错误。在
要理解这一点,请不要争论:
当我们运行这个程序时:
^{pr2}$这就是},因此它们的{}方法都应该被调用,而且它们都继承自{},因此{}也应该被调用,但只能调用一次。
super
所做的:它确保所有的调用都按正确的顺序进行,没有重复。C
继承自A
和{如果被调用的
__init__
方法采用不同的参数,并且不能处理额外的参数(例如*args, **kwargs
),那么您将得到您所引用的TypeError
。要解决这个问题,需要确保所有方法都可以处理适当的参数。正如jornsharpe在他的文章末尾提到的,我遇到的最好的方法 处理这种情况的方法是接受
**kwargs
并提取 显式命名参数。需要提取的参数应该传入named,因此它们以kwargs显示。
您甚至可以通过将
*args
作为示例中的注释来显式地只接受命名参数,这样如果您忘记了,就会发现自己有一个TypeError。编辑:
经过一段时间的思考,我意识到我的例子是非常具体的,如果你引入另一个类或改变继承,它可能会崩溃。有两件事应该解决,以使这一点更普遍:
基类不调用super
在这个例子中,这并不重要,但是如果引入另一个类,MRO可能会改变,在基类之后有一个类,因此它应该调用super。这就引出了第二个问题:
object.__init__()
不带参数如果我们想让类(特别是BaseClass)安全地放入一个通用的多重继承结构中,在这个结构中,它的超级调用可能被分派到另一个类或对象,那么我们需要在使用它们时将参数从kwargs中弹出。
{cd4>在这个名字里加上了两个相同的复杂度,但不需要。我想关键是让多重继承以一般的方式工作是困难的。
以下是一篇有趣的文章(通过google找到)关于一些细节:article
我相信你不能用
super
来做这个。你必须使用“旧风格”:相关问题 更多 >
编程相关推荐