覆盖多个孩子的父功能

时间:2018-03-06 23:30:05

标签: python-3.x inheritance multiple-inheritance

我想要使用几个子类,但是它们都从父级继承了一个方法,并不像我需要的那样。

class ParentClass():
    def __init__(self, value):
        self.value = value
    def annoying_funct(self):
        print("I don't do quite what's needed and print {0}".format(self.value + 1))
    def other_parent(self):
        print("I do other useful things my children inherit")

class Child1(ParentClass):
    def __init__(self, value, new_value1):
        super(Child1, self).__init__(value)
        self.new_value1 = new_value1
    def other_child1(self):
        print("I do useful child things")

class Child2(ParentClass):
    def __init__(self, value, new_value2):
        super(Child2, self).__init__(value)
        self.new_value2 = new_value2
    def other_child2(self):
        print("I do other useful child things")

我想覆盖annoying_funct(),如下所示:

def annoying_funct():
    print("I behave the way I am needed to and print {0}".format(self.value))

ParentClassChild1Child2来自一个非常复杂的库(scikit-learn),因此我希望尽可能地保留所有包装器。什么是最干净/最pythonic的方式来获得我的两个子类的功能,同时根据需要改变父类?

到目前为止我的想法:

创建一个继承自父级的新类,该类覆盖我不喜欢的函数,然后为从新类和子类继承的子级创建包装类。

class NewParentClass(ParentClass):
    def annoying_funct(self):
        print("I behave the way I am needed to and print {0}".format(self.value))

class NewChild1(NewParentClass, Child1):
    pass

class NewChild2(NewParentClass, Child2):
    pass

我的困惑之处:

  1. 这是正确的做法吗?这似乎有点奇怪和克鲁吉。有没有更清洁的方法呢?
  2. 两个子类的语法是否正确?它适合我,但看起来有点奇怪,让他们什么也不做,只能继承并通过。
  3. 让我的新父母从前一个父母继承正确的方法吗?该代码针对没有parentClassnewParentClass之间继承的子项运行(例如def newParentClass():),但如果有人试图创建newParentClass()的实例,则该函数将不会; t工作,因为它使用该类中不存在的属性(value)。如果我认为该课程永远不会被使用,那可以吗?

2 个答案:

答案 0 :(得分:0)

有几种方法可以做你要求的。

  1. 创建一个继承自父类的新类,然后将其用作新的父类。
  2. 此解决方案的唯一缺点是,当您向需要原始Parent类的函数提供新的父类或子类时,可能无法正常工作,因为它们可能使用annoying_funct并依赖于恼人的行为。

    class NewParentClass:
        def annoying_funct(self):
           print("I behave the way I am needed to and print {0}".format(self.value))
    
    class NewChild1(NewParentClass):
        pass
    
    class NewChild2(NewParentClass):
        pass
    
    1. 操纵现有的Parent类
    2. 这是我想要使用的解决方案,因为它通过将其替换为行为良好的annoying_funct完全销毁,再次购买,需要前annoying_funct的其他方法和功能可能会失败。好的一面是,您不需要创建另一个父类和子代,因此您的代码将更加优雅。

      class ParentClass():
          ...
          def annoying_funct(self):
              print("I don't do quite what's needed and print {0}".format(self.value + 1))
         ...
      
      
      def well_behaving_func(s):
          print("Good")
      
      # Dynamically change the class method    
      ParentClass.annoying_func = well_behaving_func
      
      class Child1(Parent):
          pass
      
      class Child2(Parent):
          pass
      
      c = Child1()
      c.annoying_funct() # prints 'Good'
      
      1. 在继承之前,向父类添加一个表现良好的新方法。
      2. 如果您想维护当前行为并且不希望现有代码或包依赖于父类中断,那么您当然不应该覆盖父类中的annoying_funct。所以你应该定义一个行为良好的函数并在子类中使用它。

        class ParentClass():
            ...
            def annoying_funct(self):
                print("I don't do quite what's needed and print {0}".format(self.value + 1))
           ...   
        
        def well_behaving_func(s):
            print("Good")
        
        # Dynamically change the class method    
        ParentClass.well_behaving_func = well_behaving_func
        
        class Child1(Parent):
            pass
        
        class Child2(Parent):
            pass
        
        c = Child1()
        # use 'well_behaving_func', not the annoying one
        c.well_behaving_func() # prints 'Good'
        

答案 1 :(得分:0)

我最终做的是使用mixin的概念将我的新功能添加到子类。结果代码如下:

class AnnoyMixin:
    def well_behaving_func(self):
        print("I behave the way I am needed to and print {0}".format(self.value))

class NewChild1(AnnoyMixin, Child1):
    def annoying_funct(self):
        return well_behaving_func(self)

class NewChild2(AnnoyMixin, Child2):
    def annoying_funct(self):
        return well_behaving_func(self)

从功能上讲,这与我在我的问题中提出的代码大致相同,但这些修改有助于提高可读性。首先,通过将新父命名为“Mixin”,它清楚地表明该类不是为了独立而设计,而是为了向另一个类添加功能。因此,AnnoyMixin不需要从ParentClass继承,从而简化了NewChild类的继承。

其次,我们创建新函数annoying_funct,而不是覆盖AnnoyMixin中的well_behaving_func。然后通过调用NewChild来覆盖annoying_funct well_behaving_func类作业。从功能上讲,这与AnnoyMixin覆盖annoying_funct的工作方式大致相同,但这样,读取annoying_funct被覆盖NewChild的代码更加清晰。 {1}}课程。