【问题标题】:Can Super deal with multiple inheritance?Super能处理多重继承吗?
【发布时间】:2011-12-15 17:55:38
【问题描述】:

当从两个这样的对象继承时

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

class Bar(object):
  def __init__(self,b):
    self.b=b

我通常会做这样的事情

class FooBar(Foo,Bar):
  def __init__(self,a,b):
    Foo.__init__(self,a)
    Bar.__init__(self,b)

super 如何知道我是否要同时调用两者?如果是这样,它将如何知道将哪个参数传递到哪里。还是根本不可能在这里使用超级用户?

即使 Foo 和 Bar 采用相同的参数,super 也能处理这个问题吗?

或者我不应该一开始就尝试这样做?

【问题讨论】:

标签: python multiple-inheritance


【解决方案1】:

使用super()__init__() 和多重继承有点棘手。

在正常的流程中,每个方法都会调用super(),而仅从object继承的类会做一些额外的工作来确保该方法确实存在:它'看起来有点像这样:

>>> class Foo(object):
...     def frob(self, arg):
...         print "Foo.frob"
...         if hasattr(super(Foo, self), 'frob'):
...             super(Foo, self).frob(arg)
... 
>>> class Bar(object):
...     def frob(self, arg):
...         print "Bar.frob"
...         if hasattr(super(Bar, self), 'frob'):
...             super(Bar, self).frob(arg)
... 
>>> class Baz(Foo, Bar):
...     def frob(self, arg):
...         print "Baz.frob"
...         super(Baz, self).frob(arg)
... 
>>> b = Baz()
>>> b.frob(1)
Baz.frob
Foo.frob
Bar.frob
>>> 

但是当你尝试在 object 实际拥有的方法上做类似的事情时,事情会变得有点冒险; object.__init__ 不带参数,因此使用它的唯一安全方法是不带参数调用super().__init__(),因为该调用可能object.__init__ 处理。但它可能object.__init__ 处理,而是由继承图中其他位置的类处理。因此,任何类在多继承类层次结构中定义__init__必须准备好以无参数调用。

解决这个问题的一种方法是永远不要在__init__() 中使用参数。做最少的初始化,并依靠设置属性或使用其他方式在使用前配置新对象。不过,这很不愉快。

另一种方法是仅使用关键字参数,例如def __init__(self, **keywords):,并始终删除适用于给定构造函数的参数。这是一个基于希望的策略,您希望在控制权到达object.__init__ 之前消耗所有关键字。

第三种方法是为所有可多重继承的基定义一个超类,它本身以某种有用的方式定义了__init__,并且调用super().__init__object.__init__ 是否- 无论如何)。这意味着您可以确定始终最后调用此方法,并且您可以随心所欲地处理参数。

【解决方案2】:

或者我不应该一开始就尝试这样做吗?

正确。您应该只调用__init__s 的一个父行,而不是树。 super 将使用 MRO 对父类进行深度优先搜索,以寻找合适的 __init__ 进行调用。它不会也不应该调用所有可能的__init__s。

【讨论】:

  • 但是如果我想:) 假设我有一个类A,我想要新的线程类B,它的行为类似于A。我不需要为threading.ThreadA 打电话给__init__ 吗?
  • 当你的生活更轻松时,使用组合而不是继承。
  • @GP89:这可能是另一个问题的基础(例如,我如何重构 MI 以使用组合......)
猜你喜欢
  • 1970-01-01
  • 2016-02-25
  • 2017-07-30
  • 2020-07-24
  • 2020-07-05
  • 2014-07-01
  • 1970-01-01
  • 2022-01-20
  • 2018-11-06
相关资源
最近更新 更多