"""Guido, the original author of Python, explains method overriding this
way: "Derived classes may override methods of their base classes.
Because methods have no special privileges when calling other methods of
the same object, a method of a base class that calls another method
defined in the same base class, may in fact end up calling a method of a
derived class that overrides it. (For C++ programmers: all methods in
Python are effectively virtual.)" """
So, I set out to create such case:
class A(object):
def __init__(self):
print "A"
def met(self):
print "I'm A's method"
def overriden(self):
print "I'm A's method to be overriden"
def calling_overriden(self):
self.overriden()
class B(object):
def __init__(self):
print "B"
def met(self):
print "I'm B's method"
class C(A):
def __init__(self, arg):
print "C","arg=",arg
A.__init__(self)
def met(self):
print "I'm C's method"
class D(B):
def __init__(self, arg):
print "D", "arg=",arg
B.__init__(self)
def met(self):
print "I'm D's method"
class E(C,D):
def __init__(self, arg):
print "E", "arg=",arg
C.__init__(self, arg)
D.__init__(self, arg)
def some(self):
self.met()
def overriden(self):
print "I'm really E's method"
e = E(10)
print 'MRO:', ' '.join([c.__name__ for c in E.__mro__])
e.some()
e.calling_overriden()
Result:
...
MRO: E C A D B object
I'm C's method
I'm really E's method
Is what I concocted in e.calling_overriden() == what Guido said on base
class sometimes calling overriden method instead of its own original method?
Regards,
mk
> Found in Dive into Python:
>
> """Guido, the original author of Python, explains method overriding
> this way: "Derived classes may override methods of their base
> classes. Because methods have no special privileges when calling other
> methods of the same object, a method of a base class that calls
> another method defined in the same base class, may in fact end up
> calling a method of a derived class that overrides it. (For C++
> programmers: all methods in Python are effectively virtual.)" """
>
> So, I set out to create such case:
>
> class A(object):
> def __init__(self):
> print "A"
>
> def met(self):
> print "I'm A's method"
>
> def overriden(self):
> print "I'm A's method to be overriden"
>
> def calling_overriden(self):
> self.overriden()
[...]
> class E(C,D):
> def __init__(self, arg):
> print "E", "arg=",arg
> C.__init__(self, arg)
> D.__init__(self, arg)
>
> def some(self):
> self.met()
>
> def overriden(self):
> print "I'm really E's method"
>
> e = E(10)
> print 'MRO:', ' '.join([c.__name__ for c in E.__mro__])
> e.some()
> e.calling_overriden()
>
>
> Result:
> ...
> MRO: E C A D B object
> I'm C's method
> I'm really E's method
>
>
> Is what I concocted in e.calling_overriden() == what Guido said on
> base class sometimes calling overriden method instead of its own
> original method?
Yes!
--
Arnaud
For a change I achieved resounding success with Python. :-)
P.S. Method resolution order in Python makes me want to kill small kittens.
Regards,
mk
mro is only a "problem" when using MI.
Oh sure! And I have the impression that multiple inheritance is not used
all that often. What (some) Python code I've read in open source
projects typically uses single inheritance.
Nevertheless MI is there in Python, might be useful in some cases and
Guido put it there for some reason, so Citizens Aspiring To Become
Pythonistas like me work to learn it.
Regards,
mk
In case you're not familiar with it, MI allows you to have mixins &
traits. They work very well if the mixin superclasses don't have any
clashes with the other superclasses, so each mixin adds its own unique
set of methods to the derived class. Then you don't have to worry
about mro and all that (at least as much).
Here's an article on it, with examples:
http://www.linuxjournal.com/node/4540/print
Michele Simionato has some criticism of MI pitfalls and has come up
with the straits module to remedy it -- you might be interested. He
goes into detail here:
http://www.artima.com/weblogs/viewpost.jsp?thread=246488
Kurt
> In case you're not familiar with it, MI allows you to have mixins &
> traits. They work very well if the mixin superclasses don't have any
> clashes with the other superclasses, so each mixin adds its own unique
> set of methods to the derived class. Then you don't have to worry
> about mro and all that (at least as much).
>
> Here's an article on it, with examples:
>
> http://www.linuxjournal.com/node/4540/print
>
> Michele Simionato has some criticism of MI pitfalls and has come up
> with the straits module to remedy it -- you might be interested. He
> goes into detail here:
>
> http://www.artima.com/weblogs/viewpost.jsp?thread=246488
Thanks Kurt, I will certainly look into that!
Regards,
mk
Much more complicated than needed for this point, but I believe yes.
Single inheritance does indeed cover most of the needs - and FWIW, even
single inheritance is not used as much in Python as in some other more
mainstream OOPLs. This comes partly from duck typing - inheritance is
only used for implementation inheritance, not for type-based polymorphic
dispatch -, and partly from Python's support for composition/delegation
(thru __getattr__). Also - as you noticed - single inheritance is easier
to grasp, and Python's philosophy really values simplicity, readability,
maintainability, and coder's mental health !-)
> Nevertheless MI is there in Python, might be useful in some cases and
> Guido put it there for some reason,
Indeed. As with most Python's "advanced" features, it's there so you can
use it when appropriate.
> so Citizens Aspiring To Become
> Pythonistas like me work to learn it.
FWIW, I very rarely had to use it myself in almost 10 years of Python
programming - main exceptions being Zope2 stuff (which is IMHO highly
unpythonic) and a couple mixin classes here and there.