Python3泛型继承层次结构

Python3泛型继承层次结构,python,python-3.x,inheritance,generic-programming,metaclass,Python,Python 3.x,Inheritance,Generic Programming,Metaclass,这个问题专门针对Python3。假设我有这样一个类层次结构 class Base(): def calculate(): return 0 class Derived1(Base): def calculate(): # some calculation class Derived2(Base): def calculate(): # some calculation 现在,我要做的是创建一个类,该类定义了从派生类继

这个问题专门针对Python3。假设我有这样一个类层次结构

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

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

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

现在,我要做的是创建一个类,该类定义了从派生类继承的通用方法,然后重写计算。换句话说,在C++模板的精神中,避免复制子类代码,但指定一种通用的子类方法,然后能够将子类定义为一个内层,如下面所示:

# 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中的哪些相关工具?我听说过元类,但不是很熟悉。

工厂函数体中的类定义 去那里最直接的方法其实很简单,但可能会感到有点尴尬:

def派生的_5_工厂(基本):
类GenericDerived5(基):
def计算(自我):
返回super().calculate()+5
返回GenericDerived5
def衍生6_工厂(基本):
类GenericDerived6(基):
def计算(自我):
返回super().calculate()+6
返回GenericDerived6
Derived5_1=派生工厂(Derived1)
Derived6_2=派生工厂(Derived2)
不方便的部分是您的类需要泛型基 必须在功能体内部定义。这样,Python将重新执行
语句本身具有不同的基,利用了 Python类中的对象是第一类对象

该代码的不便之处在于:(1)类主体必须位于函数内部,(2)它可能是一种错误的方法:

多重继承 如果您可以有一个额外的继承级别——这是您的示例的唯一区别,那么这就是“正确”的方法。实际上,除了在继承链中显式地包含以前的“GenericDerivated”类外,它们的行为将完全符合预期:


类基():
def calculate():
返回0
派生类1(基本类):
def计算(自我):
返回1
派生类2(基本类):
def计算(自我):
返回2
#混入碱:
类别MixinDerived5(基本):
def计算(自我):
返回super().calculate()+5
类别MixinDerived6(基本):
def计算(自我):
返回super().calculate()+6
Derived5_1=类型(“Derived5_1”,(MixinDerived5,Derived1),{})
Derived6_2=类型(“Derived6_2”,(MixinDerived6,Derived2),{})
这里,不使用
class
语句,而是使用
type
调用创建动态类,使用需要动态基的类和该动态基作为其
base
参数。也就是说-
Derived5_1
是一个完全工作的Python类,其继承链中有两个基

请注意,Python的
super()
将完全按照常识所期望的那样,在到达“Base”之前通过额外的中介“派生”类“重新路由”。这就是我在粘贴上面的代码后在交互控制台上得到的结果:

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

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

粗略地说,mix-in-class是一个类,它不打算直接实例化或作为独立的基类(除了其他更专业的mix-in-class),而是提供另一个类可以继承的一小部分功能

在这种情况下,您的
GenericDerived
类是混合集成的完美示例:您没有创建
GenericDerived
的实例,但您可以从它们继承来向您自己的类添加
calculate
方法

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):
    ...
请注意,
Base
Calculator
层次结构彼此独立
Base
除了提供其他功能外,还提供基本的
计算功能。
Base
的子类可以使用它从
Base
继承的
Calculator
,也可以从
Calculator
的子类继承

class Derived1(Base):
    ...

class Derived2(Base, Calculator1):
    ...

class Derived3(Base, Calculator2):
    ...

我不确定是否值得在答案中拖拽一个显式调用
type
class Derived5_1(MixinDerived5,Derived1):…
也可以工作。factory函数方法的问题是每次调用它时实际上都在创建单独的
GenericDerived*
类,意味着两个类看起来好像来自同一个类,而类型通常做正确的事情。类型似乎是问题的精神,因为我在寻找类似于C++模板的东西,在某种程度上。我们将进一步研究这一问题。请重新阅读此问题,并在此处添加一些详细信息。factory函数应添加缓存机制,以避免在每次调用中重新创建类。然而,如果你真的想让一个类表现得像是从另一个基派生出来的,这取决于它的调用方式——这是很棘手的——它可以通过某种机制来完成,这种机制应该被用来代替
super()
,并且可以放在一个元类上。你能解释一下你想做什么吗?显然,您已经知道类定义和继承了,为什么不使用这个工具来解决这个问题呢
class Derived5_1(GenericDerived5,Derived1)
应该做你想做的事情,这几乎是一字不差的问题。我在问题中说的:“从派生类继承的通用方法”。与其显式地指定基类和派生类的所有组合,不如定义一种通用的继承方式,可能使用类型,然后只将类定义为一行程序。多重继承也是一行代码。如前所述,它几乎与伪代码一字不差。你能不能澄清一下你还需要什么,或者mixin与你想要的有什么冲突?我知道mixin。这不是我想要的,与问题无关