Python继承。为什么这么乱?

时间:2012-05-09 03:01:49

标签: python syntax

  

可能重复:
  Why aren't Python's superclass init methods automatically invoked?

例如:

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类中调用init的宠物?为什么不只是把它称为狗类的第一行(类狗(宠物))?它似乎只会创建更混乱的代码。它有点像Python一样杀死了Python的继承点。

2 个答案:

答案 0 :(得分:9)

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

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

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

在python 2中:

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

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

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

修改

由于你实际上并没有使用传递给dog的name参数,你可以通过接受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

在您的场景中,初始化程序可能很简单,不需要这个,但知道何时有更多参数和/或更深层次的层次结构是很有用的。

答案 1 :(得分: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