An inheritance question: getting the name of the "one up" class

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Tue Mar 31 06:29:50 CEST 2009


En Tue, 31 Mar 2009 00:13:44 -0300, Nick <mediocre_person at hotmail.com>  
escribió:

> I've got a collection of classes describing animals, part of which looks  
> like:
>
> class Animal(object):
>     def __init__(self):
>         self.pet = False
>         self.edible = False
>         self.legs = 0
>         self.sound = None
>         self.name = self.__class__.__name__.lower()
>
> class Mammal(Animal):
> class Primate(Mammal):
> class Human(Mammal):

(shouldn't be Primate?)

> I want to add a "pedigree" function to Animal so that I can have:
>
>>>> h = Human()
>>>> h.pedigree()
> human < primate < mammal < animal

The subject says `getting the name of the "one up" class` but Python  
allows for multiple inheritance, so you could have several "one up"  
classes.
Classes have a mro ("method resolution order") that linearizes the  
inheritance tree in a very specific way. In the case of single  
inheritance, it returns the sequence of base clases, from last to first  
(object).

Human.mro() yields:
[<class 'a.Human'>, <class 'a.Primate'>, <class 'a.Mammal'>, <class  
'a.Animal'>, <type 'object'>]

We have to omit the last element and take the __name__ of each class. And  
this is clearly a class method: it doesn't depend on any instance. Let's  
add this to the Animal class:

     @classmethod
     def pedigree(cls):
         return ' < '.join(base.__name__ for base in cls.mro()[:-1])

Human.pedigree() returns:
Human < Primate < Mammal < Animal

> I've been thinking about something like:
> def pedigree(self):
>     n = self.name
>     while n != 'object' # base class of Animal
>         print n,
>         n = Well, this is where I'm stuck. super(???,???).???
>     print

You can't use self.name here -- I assume you want *class* relationships,  
so you can't use instance data, ok?
Each class has a __bases__ attribute, and assuming you only have single  
inheritance, the "one up" class is __bases__[0] -- you could write  
pedigree() now using __bases__[0].
(But I'd let Python do the hard work and use mro() instead...)

> Oh, and while the gurus are at it, what would be the advantage (if any)  
> of changing, say
>    Primate.__init__(self)
> to
>     super(Human, self).__init__()

None, if you use single inheritance everywhere.

super is very tricky; see:
http://fuhm.net/super-harmful/
and
http://www.artima.com/weblogs/viewpost.jsp?thread=236275

-- 
Gabriel Genellina




More information about the Python-list mailing list