[Tutor] super() with Multiple Inheritance
Steven D'Aprano
steve at pearwood.info
Fri Apr 15 02:48:13 CEST 2011
James,
Your subject line is misleading: you ask about *multiple* inheritance,
but the code you use is *single* inheritance:
object
-> Element
-> Vertex
-> Person
-> User
Multiple inheritance occurs when you have a class that inherits from two
or more parent classes:
class Spam(Ham, ManufacturedMeatProduct):
[...]
This is often problematic, so much so that many object oriented
languages prohibit it, or limit it to a subset of MI where the second
parent shares no methods with the first ("mixins").
Python allows almost unrestricted MI, but I strongly recommend that you
avoid it unless absolutely necessary.
Also, it's quite unusual in Python to build long inheritance chains like
this. We're a pragmatic people, we Python coders, and if a class only
exists to satisfy some sense of theoretical object-hierarchy purity,
more often than not we prefer the Zen of Python:
>>> import this
[...]
Practicality beats purity.
I'd consider reducing the hierarchy to:
object
-> Element
-> User
unless you have real need for the other classes.
James Thornton wrote:
> Why does user.params() not return all the params up the inheritance
> chain? -- It's not including the params defined in Person() -- notice
> Vertex() does not have a params() method.
You do something fairly unusual here:
> class Person(Vertex):
> def __init__(self,name=None,uri=None,email=None):
> self.s = super(Person,self)
> self.s.__init__()
I've never seen anyone *store* a super object before! Normally people
generate it as needed:
super(Person, self).__init__()
This leads to your mistake:
> class User(Person):
> def __init__(self, [...])
> self.s = super(User,self)
> self.s.__init__(name,uri,email)
So you store the User's super object as attribute "s", and then call the
superclasses' __init__ method... but Person's __init__ in turn *also*
stores its super object as "s", thus *over-writing* the "s" you just
saved. Then, when you call params:
> def params(self):
> params = dict(...)
> print self.s.params()
> params.update(self.s.params())
> return params
self.s is the super object for Person, not User, and so it skips Person
and goes directly to Vertex, Element and object.
TL;DR: don't save super objects for later use, they're not that
expensive to make. Just regenerate them as needed.
--
Steven
More information about the Tutor
mailing list