Steven D'Aprano wrote:
On Sun, 25 Jul 2010 13:58:00 +1200, Gregory Ewing wrote:
Lacrima wrote:
But what if SuperClass1 is from third party library?
If it hasn't been designed for super(), then you can't use super() with
it.
super() only works when *every* class in the hierarchy has been designed
with it in mind.
That incorrect. You can certainly use super() with classic classes in the
hierarchy, and super() didn't even exist when they were created.
class Parent:
... def method(self, arg):
... return repr(arg)
...
class Classic(Parent):
... def method(self, arg):
... return "argument was %s" % Parent.method(self, arg)
...
class New(object, Classic):
... def method(self, arg):
... return super(New, self).method(arg).upper()
...
x = New()
x.method('spam')
"ARGUMENT WAS 'SPAM'"
The problem isn't super(), and people who give glib advise "don't use
super()" are just compounding the problem. The problem is with multiple
inheritance where methods have different method signatures. If you don't
change the method signatures, super() will work fine.
Advising people not to use super() might make people feel virtuous, but
it doesn't do anything to help the reader write non-buggy MI hierarchies.
It pushes the effort of dealing with multiple inheritance onto them,
forcing them to re-implement the MRO, probably badly. Can you re-
implement the C3 algorithm? Have you even heard of it? If you answer No
to either of those questions, chances are high that trying to deal with
the MRO manually will lead to worse bugs than using super().
Should you use super()?
1. If you're doing multiple inheritance with metaclasses, you MUST use
super().
2. If you're using single inheritance only, and never modify method
signatures, there is no reason not to use super().
3. If you're using mixins, you should use super().
4. If you never modify method signatures, then you should use super().
5. If you do modify method signatures, you shouldn't do that (except
possibly in constructors, and even there only cautiously). But if you do
it anyway, then you should use super() *except* in the methods where you
modify the signature.
6. If you don't use super(), chances are that your class hierarchy is
still buggy, but instead of failing loudly and noisily with an exception,
it's silently giving the wrong results.
7. If you can avoid multiple inheritance in favour of another technique
(such as composition), you should strongly consider that.
I think you're missing the point that super for most of us is a
dangerous guess game. It makes implicit what would *really* need to be
explicit.
class Base1(object):
def foo(self):
print 'Base1'
class Base2(object):
def foo(self):
print 'Base1'
class Sub(Base1, Base2):
def foo(self):
# which base version to call ???
# choice A
# use super an pray that it will do what I need (better
know exactly how the MRO works)
# also pray that further readers know as much as I do
about super
# choice B
# use explicit calls so I can choose which algorithm I
want to use, calling Base1, Base2 or both of them
# If the choice is too difficult, that means one thing
=> my inheritance design is crap => rewrite it properly.
Super is known for being required for diamond inheritance, and this
reputation is well earned. Outside this scope, super's not required.
JM
--
http://mail.python.org/mailman/listinfo/python-list