代码之家  ›  专栏  ›  技术社区  ›  kjo

实现“钻石继承”的Python方式是什么?

  •  3
  • kjo  · 技术社区  · 11 年前

    我面临着一个近乎教科书式的钻石继承问题。(相当做作!)下面的示例捕获了它的所有基本特征:

    # CAVEAT: error-checking omitted for simplicity
    
    class top(object):
        def __init__(self, matrix):
            self.matrix = matrix  # matrix must be non-empty and rectangular!
    
        def foo(self):
            '''Sum all matrix entries.'''
            return sum([sum(row) for row in self.matrix])
    
    class middle_0(top):
        def foo(self):
            '''Sum all matrix entries along (wrap-around) diagonal.'''
            matrix = self.matrix
            n = len(matrix[0])
            return sum([row[i % n] for i, row in enumerate(matrix)])
    
    class middle_1(top):
        def __init__(self, m, n):
            data = range(m * n)
            matrix = [[1 + data[i * n + j] for j in range(n)] for i in range(m)]
    
            super(middle_1, self).__init__(matrix)
    

    总之,类 middle_0 和 middle_1 都是类的子类 top 哪里 中间_0 重写方法 foo 和 中间_1 重写方法 __init__ 。基本上,经典的钻石继承设置。对基本模式的一个阐述是 middle_1.__init__ 实际调用父类的 __初始化__ 。(下面的演示显示了这些类的实际操作。)

    我想定义一个类 bottom “得到” 1. 食品 从…起 中间_0 和 __初始化__ 从…起 中间_1 .

    实现这样一个目标的“蟒蛇方式”是什么 底部 班


    演示:

    matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    print top(matrix).foo()
    # 45
    print middle_0(matrix).foo()
    # 15
    print middle_1(3, 3).foo()
    # 45
    
    # print bottom(3, 3).foo()
    # 15
    

    1. 我写“gets”而不是“inherits”,因为我怀疑使用标准Python继承无法轻松解决这个问题。

    2 回复  |  直到 11 年前
        1
  •  4
  •   Martijn Pieters    11 年前

    bottom 简单地从两者继承;您的类没有什么特别之处,这会使本案例变得特别:

    class bottom(middle_0, middle_1):
        pass
    

    演示:

    >>> class bottom(middle_0, middle_1):
    ...     pass
    ... 
    >>> bottom(3, 3).foo()
    15
    

    这可以按预期工作,因为Python会同时安排 middle_0 和 middle_1 之前要搜索的方法 top 是:

    >>> bottom.__mro__
    (<class '__main__.bottom'>, <class '__main__.middle_0'>, <class '__main__.middle_1'>, <class '__main__.top'>, <type 'object'>)
    

    这显示了 方法解决顺序 班级的;这是用来寻找方法的顺序。所以 bottom.__init__ 在上找到 中间_1 和 bottom.foo 在上找到 中间_0 ,如前所列 顶部 .

        2
  •  2
  •   socrates    11 年前

    我认为

    一个从middle0“得到”1个foo,从middle1“得到”__init__的类底部。

    将由以下人员完成

    class bottom(middle_0, middle_1):
        pass