【问题标题】:Python multiple inheritence issuesPython 多重继承问题
【发布时间】:2012-08-08 09:08:59
【问题描述】:

我正在尝试运行具有如下继承模式的 python 代码:

A Object
|   /\
|  B C
|  | |
|  D E
 \ | /
  \|/
   F
A = Base Handler
B = OAuth2 Mixin
C = OAuth Mixin
D = Facebook Graph Mixin
E = Twitter Mixin

B、C、D、E 中的函数名称重叠。 D 和 E 是 mixin,所以它们不应该独立产生。我该如何解决这个问题,以便 F 类可以调用特定的 mixin?

【问题讨论】:

  • 如果你需要在 B 中调用一个函数的实现,即使 E 间接地从它扩展而来,你的代码在某处也有一些非常错误的地方。你真的打算扩展它们,而不是使用聚合吗?
  • 如何聚合成一个类?这使用导入还是什么?附言我不需要调用B中的版本,我只需要调用C和D中的版本,它们同名。
  • 然后在你的 E 类(作为属性)中有一个 C 和 D 的实例,而不是从这些实例扩展。

标签: python multiple-inheritance tornado mixins


【解决方案1】:

重新考虑从两者继承是否是真的你想要做的。如果你只从 A 和 C 继承,并且只保留一个 D 的实例,就像这样:

class E(A, C):
   def __init__(self):
      self.d = D()

,然后self.foo() 向上移动到B.foo。要拨打D.foo,您可以拨打self.d.foo()。您还需要在E 中显式包装您想要的D 的任何其他方法 - 如果您使用的是 Python 3,则非常简单:

def __init__(self):
    self.d = D()
    self.bar = d.bar

在 Python 2 中,这是行不通的,最简单的方法是像这样编写包装器:

def bar(self):
   return self.d.bar()

【讨论】:

    【解决方案2】:

    如果您提前知道CD 的名称,您可以调用它们的方法并显式传递self

    class E(C, D):
        def do_c_thing(self):
            # Call C's version
            C.some_method(self, ...)
    
        def do_d_thing(self):
            # Call D's version
            D.some_method(self, ...)
    

    【讨论】:

    • 当我尝试这样做时,它仍然调用 C 的副本。 (我可以说,因为当我在类 def 中切换顺序时,一半代码开始工作,另一半停止)
    • 你确定吗?请记住,很多 Tornado 代码都是基于回调的,因此如果 D 的副本中的任何内容执行类似于 add_callback(self.foo) 的操作,那么即使是 @ 987654327@ 最初调用的副本。如果您所调用的内容使用回调,则您可能不需要继承,而只需创建子对象并对其进行调用。
    • 我想一定是这样。我没有意识到 D 中的回调会检查 E 的 MRO。唯一的问题是技术上 B、C 和 D 是 Mixin,因此它们不应该作为对象生成。 (我在做oauth,C和D是facebook/twitter,B是Oauth2)
    • 什么是A? OAuth2 似乎是自给自足的。
    • A 是一个 Base Web 请求处理程序,定义了当前 facebook 和 twitter 用户。
    猜你喜欢
    • 2021-05-08
    • 2020-07-05
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    相关资源
    最近更新 更多