Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python inheritance. Why is it so messy? [duplicate]

Tags:

python

syntax

Possible Duplicate:
Why aren't Python's superclass init methods automatically invoked?

For example:

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

As you can see Dog inherits from pet. I understand the code perfectly fine. But why must we call the init for pet in the Dog class? Why isn't just calling it as in the first line of the dog class enough ( class Dog(Pet) )? It seems to only create messier code. It kind of kills the point of inheritance in Python to me.

like image 261
VPNTIME Avatar asked Dec 12 '22 02:12

VPNTIME


1 Answers

Having the language force the super class to initialize before or after means that you lose functionality. A subclass may depend on a superclass's initialization to be run first, or vice versa.

In addition, it wouldn't have any way of knowing what arguments to pass -- subclasses decide what values are passed to an initializer, which gives more flexibility over automatically passing all arguments.

An alternative method of initializing the super-class is by using super, though this will actually initialize the super-class of self dynamically, by looking it up in the object's __mro__ (method resolution order)

In python 2:

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

In python 3, you can further reduce the syntax, and avoid repeating yourself:

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

Edit:

Since you're not actually using the name argument passed to dog, you can further reduce some syntax, by accepting arbitrary keyword and positional arguments in the Dog initializer, and passing them up the initialization chain:

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

In your scenario, the initializer might be simple enough to not need this, but it's useful to know for when you have more arguments, and/or a deeper class hierarchy.

like image 77
Casey Kuball Avatar answered Dec 27 '22 05:12

Casey Kuball