【问题标题】:Adding on to inherited initialization?添加到继承的初始化?
【发布时间】:2013-01-08 22:04:01
【问题描述】:

假设我有一些创建类的代码:

class Item:
    def __init__(self, param1):
        do something with param1

现在假设我有一个对象 ItemChild,它继承自该类并继承其初始化函数,即有一些代码调用 Item 的 __init__ 函数。但是,假设我还希望它在其__init__ 函数中做更多事情,并且我希望它使用更多参数,即 param1、param2、param3 和 param4。似乎对父级的__init__ 函数的调用现在会被混淆,因为当我将参数 1-3 传递给 ItemChild 的实例时,它不知道哪个参数是 param1。有没有办法解决这个问题,或者初始化方法的继承仅限于该方法并且不能扩展?

【问题讨论】:

    标签: python


    【解决方案1】:

    以下是处理此类场景的正确方法:

    class Item(object):
        def __init__(self, param1):
            # do something with param1
    
    class ItemChild(Item):
        def __init__(self, param1, param2, param3, param4):
            super(ItemChild, self).__init__(param1)
            # do something with params
    

    请注意,Item 继承自 object 很重要,因为 super() 仅适用于新型类。

    如 cmets 中所述,在 3.x 中,您不需要包含 super() 的参数,您只需使用 super().__init__(param1)

    【讨论】:

    • 请注意,在 3.x 中,您可以使用新的 super(),它有一些魔力并且不需要参数。
    【解决方案2】:

    它实际上会反过来工作 - ItemChild__init__ 方法将首先被调用,并且只能转发适合 Item 的内容:

    class Item:
        def __init__(self, param1):
            print "Item.__init__ doing something with param1"
            # do something with param1
    
    
    class ItemChild(Item):
        def __init__(self, param1, param2, param3):
            print "Starting ItemChild.__init__"
            super(ItemChild, self).__init__(param1)
            print "ItemChild.__init__ doing something with params 2 and 3"
            # do something with param2 and param3
    

    当您拨打ItemChild(1, 2, 3)时,流程如下:

    Starting ItemChild.__init__
    Item.__init__ doing something with param1
    ItemChild.__init__ doing something with params 2 and 3
    

    不是:

    Item.__init__ doing something with param1
    Starting ItemChild.__init__
    ItemChild.__init__ doing something with params 2 and 3
    

    当然,您可以重新安排您的 super 调用,使其在您执行其他操作之前或之后运行 - 或者如果您不想让父母的行为运行,您可以完全忽略它。

    【讨论】:

      【解决方案3】:

      不,只需根据需要委托孩子的__init__ 中的参数即可。

      class Parent(object):
          def __init__(self, x, y):
              self.x = x
              self.y = y
      
      class Child(Parent):
          def __init__(self, w, x, y, z):
              Parent.__init__(self, x, y)
              self.w = w
              self.z = z
      
      p = Parent(1, 2)
      # p.x == 1
      # p.y == 2
      c = Child(1, 2, 3, 4)
      # c.w = 1
      # c.x = 2
      # c.y = 3
      # c.z = 4
      

      您也可以使用super,如其他示例中所述。在大多数情况下,这主要是个人喜好问题,但是当您开始设计更高级的类时,差异就变得很重要。 super 将按 MRO 顺序查找类父级的 __init__() 方法,并在需要时协同调用。直接调用超类的__init__() 方法会牺牲一些用于显式控制的自动功能。此外,对于super,您必须注意孩子将发现的所有__init__() 方法都具有兼容的签名,否则您将获得异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多