4

可能重复:
为什么不自动调用Python 的超类init方法?

例如:

class Pet(object):

    def __init__(self, name, species):
       self.name = name
       self.species = species

    def getName(self):
     return self.name

    def getSpecies(self):
     return self.species

    def __str__(self):
     return "%s is a %s" % (self.name, self.species)

class Dog(Pet):

   def __init__(self, name, chases_cats):
      Pet.__init__(self, name, "Dog")
      self.chases_cats = chases_cats

   def chasesCats(self):
     return self.chases_cats

如您所见, Dog 继承自 pet。我完全理解代码。但是为什么我们必须在 Dog 类中调用宠物的 init 呢?为什么仅仅在狗类的第一行中调用它就足够了(类 Dog(Pet) )?它似乎只会创建更混乱的代码。对我来说,这有点扼杀了 Python 中的继承点。

4

2 回答 2

9

让语言强制超类在之前或之后初始化意味着您失去了功能。子类可能依赖于先运行超类的初始化,反之亦然。

此外,它无法知道要传递哪些参数——子类决定将哪些值传递给初始化程序,这为自动传递所有参数提供了更大的灵活性。

初始化超类的另一种方法是使用super ,尽管这实际上会通过在对象的(方法解析顺序)self中查找来动态初始化超类__mro__

在python 2中:

super(self, Dog).__init__(self, name, "Dog")

在 python 3 中,您可以进一步减少语法,并避免重复自己:

super().__init__(self, name, "Dog")

编辑

由于您实际上并没有使用name传递给 dog 的参数,因此您可以通过在初始化程序中接受任意关键字和位置参数Dog并将它们传递到初始化链上来进一步减少一些语法:

class Dog(Pet):

   def __init__(self, chases_cats, *args, **kwargs):
      Pet.__init__(self, *args, species="Dog", **kwargs)
      self.chases_cats = chases_cats

class Pet(object):

    def __init__(self, name, species, *args, **kwargs):
       self.name = name
       self.species = species

在您的场景中,初始化程序可能足够简单以至于不需要它,但是了解何时有更多参数和/或更深的类层次结构很有用。

于 2012-05-09T03:14:58.550 回答
4

您可以像这样使物种成为类属性

class Pet(object):
    species = None

    def __init__(self, name):
        self.name = name

    def getName(self):
        return self.name

    def getSpecies(self):
        return self.species

    def __str__(self):
        return "%s is a %s" % (self.name, self.species)

class Dog(Pet):
    species = "Dog"

    def __init__(self, name, chases_cats):
        Pet.__init__(self, name)
        self.chases_cats = chases_cats

    def chasesCats(self):
        return self.chases_cats
于 2012-05-09T03:31:07.520 回答