An inheritance question: getting the name of the "one up" class
Gabriel Genellina
gagsl-py2 at yahoo.com.ar
Tue Mar 31 00:29:50 EDT 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