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

Reply via email to