Python3泛型继承层次结构

2024-10-01 19:27:21 发布

您现在位置:Python中文网/ 问答频道 /正文

这个问题专门针对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中的哪些相关工具?我听说过元类,但不是很熟悉


Tags: 方法代码basereturn定义defsome子类
2条回答

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

在本例中,您的GenericDerived类是mix-ins的完美示例:您没有创建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):
    ...

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

class Derived1(Base):
    ...

class Derived2(Base, Calculator1):
    ...

class Derived3(Base, Calculator2):
    ...

工厂函数体中的类定义

去那里最简单的方法是真正的简单,但是会觉得有点尴尬:

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)

不方便的部分是您的类需要泛型基 必须在功能体内部定义。这样,Python将重新执行 class 语句本身,使用不同的基,利用 Python类中的对象是第一类对象

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

多重继承

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


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调用创建动态类,同时使用需要动态基的类和该动态基作为其bases参数。也就是说-Derived5_1是一个完全工作的Python类,在其继承链中有两个基

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

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

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

相关问题 更多 >

    热门问题