Python3 通用继承层次结构

Python3 generic inheritance hierarchy

这个问题是针对 python 3. 假设我有一个像这样的 class 层次结构

class Base():
   def calculate():
       return 0

class Derived1(Base):
     def calculate():
        # some calculation

class Derived2(Base):
     def calculate():
        # some calculation

现在,我想要做的是创建一个 class,它定义了一种从 Derived classes 继承的通用方法,然后覆盖计算。换句话说,本着 C++ 模板的精神,避免复制 subclasses 代码,而是指定 subclassing 的通用方式,然后能够定义 subclasses作为一个衬里,如下图:

# pseudocode
class GenericDerived5(someGenericBase):
      def calculate():
          return super().calculate() + 5

class GenericDerived6(someGenericBase):
      def calculate():
          return super().calculate() + 5

class Derived5_1 = GenericDerived5(Derived1)
class Derived6_1 = GenericDerived6(Derived2)

(计算不是字面意思,只是说明继承结构的组合性) 这段代码会是什么样子,我需要哪些来自 python3 的相关工具?听说过 metaclasses,但不是很熟悉。

class 工厂函数体内的定义

去那里最直接的方式是真的直接 - 但可能会感觉有点尴尬:

def derived_5_factory(Base):
    class GenericDerived5(Base):
        def calculate(self):
            return super().calculate() + 5
    return GenericDerived5

def derived_6_factory(Base):
    class GenericDerived6(Base):
        def calculate(self):
            return super().calculate() + 6
    return GenericDerived6

Derived5_1 = derived_5_factory(Derived1)
Derived6_2 = derived_6_factory(Derived2)

不方便的部分是您的 classes 需要通用基础 必须在函数体内定义。这样,Python 重新执行 class 语句本身,具有不同的 Base,利用 在 Python class 中是第一个 class 个对象。

此代码的不便之处在于 (1) class 主体必须在函数内部,并且 (2) 它可能是完全错误的方法:

多重继承

如果您可以拥有额外的继承级别 - 这是您的示例的唯一区别,那么这是“正确”的方法。实际上,除了在它们的继承链中明确包含前一个“GenericDerived”classes 之外,它们的行为完全符合预期:


class Base():
   def calculate():
       return 0

class Derived1(Base):
     def calculate(self):
        return 1

class Derived2(Base):
     def calculate(self):
        return 2

#  mix-in bases:

class MixinDerived5(Base):
    def calculate(self):
        return super().calculate() + 5

class MixinDerived6(Base):
    def calculate(self):
        return super().calculate() + 6


Derived5_1 = type("Derived5_1", (MixinDerived5, Derived1), {})
Derived6_2 = type("Derived6_2", (MixinDerived6, Derived2), {})

在这里,不是使用 class 语句,而是使用 type 调用创建动态 class,同时使用需要动态基础的 class 和该动态基础作为其 bases 参数。就是这样 - Derived5_1 是一个完全可用的 Python class,其继承链中包含两个 Base

请注意,Python 的 super() 将完全按照常识期望它做的事情,在到达之前通过额外的中介“派生”classes“重新路由”自己“根据”。所以,这就是我在粘贴上面的代码后在交互式控制台上得到的:

In [6]: Derived5_1().calculate()                                                                 
Out[6]: 6

In [7]: Derived6_2().calculate()                                                                 
Out[7]: 8

混合 class,粗略地说,是一个 class,它不打算直接实例化或充当独立的基础 class(除了其他,更专业的混入 classes),但提供另一个 class 可以继承的一小部分功能。

在这种情况下,您的 GenericDerived classes 是混合的完美示例:您不是在创建 GenericDerived 的实例,但您可以继承它们以添加calculate 方法到您自己的 class.

class Calculator:
    def calculate(self):
        return 9

class Calculator1(Calculator):
      def calculate(self):
          return super().calculate() + 5

class Calculator2(Calculator):
      def calculate(self):
          return super().calculate() + 10

class Base(Calculator):
    ...

请注意,BaseCalculator 层次结构彼此独立。 Base 除了提供其他功能外,还提供基本的 calculate 功能。 Base 的子 class 可以使用从 Base 继承的 calculate(通过 Calculator),或者它可以从子 class 继承也是 Calculator

class Derived1(Base):
    ...

class Derived2(Base, Calculator1):
    ...

class Derived3(Base, Calculator2):
    ...