0

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

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

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

4

3 回答 3

3

它实际上会以相反的方式工作 -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呼叫,使其在您做其他事情之前或之后运行 - 或者如果您不想让父母的行为运行,您可以完全忽略它。

于 2013-01-08T22:06:25.027 回答
3

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

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()仅适用于新型类。

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

于 2013-01-08T22:08:01.800 回答
2

不,只需根据需要委托孩子的论点__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将按__init__()MRO 顺序查找类父级的方法,并在必要时协同调用。直接调用超类的__init__()方法会牺牲一些用于显式控制的自动功能。此外,使用 时super,您必须小心__init__()孩子将发现的所有方法都具有兼容的签名,否则您将获得异常。

于 2013-01-08T22:05:16.753 回答