【问题标题】:Is it acceptable to initialize the parent class from within the subclass __init__()?从子类 __init__() 中初始化父类是否可以接受?
【发布时间】:2014-10-21 05:41:42
【问题描述】:

从子类中初始化父类,以便创建的子类实例可以使用父类属性是一种好习惯吗? 这样做是否有替代方案或最佳做法?

举个例子:

class Animal(object):
    def __init__(self, name, weight, cute=False, image=None):
        #Instantiation attributes
        self.name = name
        self.weight = weight
        self.cute = cute
        self.image = image
        #Attributes common to all animals
        self.extinct = False
    def get_animal_stats(self):
        print arbitrary_animal_stat

class Dog(Animal):
    def __init__(self, name, weight):
        Animal.__init__(self, name, weight, cute=True, image="dog.com")
        #Additional attributes unique to dogs
        self.number_legs = 4
        self.teeth = True
    def make_noise(self):
        print "Bark!"

据我了解,在子类初始化期间不初始化父类,子类对象只能访问自己的属性(即number_legs和tooth,以及make_noise)而不是父类的属性或方法(即灭绝, 和 get_animal_stats)。

我发现自己为预定义对象编写了许多小类,但必须用子对象初始化父对象。这样,我可以动态创建一个简单的 Animal,或者通过 Dog 子类创建一个更具描述性的 Animal。

从子类实例访问 Parent 属性和方法的正确方法是什么?我是否误解了子类的使用?

【问题讨论】:

    标签: python inheritance subclass


    【解决方案1】:

    这不仅是可以接受的,而且您几乎应该总是调用父类的构造函数。你不这样做的唯一原因是如果你

    1. 绝对肯定不会在父类中定义任何初始化代码,这是对象运行所必需的,并且
    2. 您想显式覆盖父类的初始化行为。

    对于新样式类(继承自对象的类),最好使用super(),因为它会在多重继承的情况下处理解析顺序。在 Python 2.7 中,使用:

    class ParentFooA(GrandparentFoo):
        def __init__(self):
            some_important_initialization_code()
    
    class ChildFoo(ParentFoo):
        def __init__(self):
            super(ChildFoo, self).__init__()
    

    请注意,另一个不错的属性是,当您定义继承时(例如,在 class ChildFoo(...) 行中),您不必在 ChildFoo 中的任何地方使用名称 ParentFoo except .它也适用于其他方法:

    class ChildFoo(ParentFoo):
        ...
        def do_buzz(self):
            super(ChildFoo, self).do_buzz()
    

    super()适用于旧式类(即不继承自 object 的类)。 这意味着对于大部分标准库,您仍然必须显式调用父类的构造函数。所以在这种情况下:

    class OldStyleParent:
        def __init__(self):
            ...
    

    您必须在__init__() 中显式调用OldStyleParent.__init__()

    在 Python 3 中,super 的语法很简单:

    class ChildFooInPython3(ParentFoo):
        def __init__(self):
            super().__init__()
    

    【讨论】:

    • 很好的答案!我有几个澄清的问题:你什么时候选择 1.?如果您确定父类中没有子类运行所需的初始化代码,那么是否应该首先对子类进行子类化? Super() 很高兴知道。根据您的回答,我理解它用于多重继承,但是明确说明您实例化的父类(关于继承堆栈)不是更好吗?
    • super() 自动适应继承结构的变化,允许您编写子类而无需(太多)了解它的父类。在 Python 中,继承堆栈不一定是线性的,super()(如果使用正确且一致)有助于消除多重继承的情况。
    • 至于 1,我将类用作“mix-ins”,它为用户定义的类提供了一些附加功能。这些“混合”主要由静态方法组成,并不需要任何初始化。我还使用抽象基类来强制执行 Java 风格的“接口”。这些类的存在使得它们的方法将被覆盖并且通常不需要任何初始化。
    【解决方案2】:

    这没什么错,尽管您可能想使用 super():

    super(Dog, self).__init__...
    

    或者在 Python 3 中:

    super().__init__...
    

    【讨论】:

      【解决方案3】:
      class Dog(Animal):
          def __init__(self, name, weight):
              super(Dog, self).__init__(name, weight, cute=True, image="dog.com")
              #Additional attributes unique to dogs
              self.number_legs = 4
              self.teeth = True
          def make_noise(self):
              print "Bark!"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-05-09
        • 1970-01-01
        • 2023-02-02
        • 1970-01-01
        • 1970-01-01
        • 2018-02-20
        • 1970-01-01
        相关资源
        最近更新 更多