On Jan 5, 2005, at 1:23 PM, Guido van Rossum wrote:
The issue of mixing super() and explicit calls to the superclass's
method occur with any method. (Thus making it difficult/impossible for
a framework to convert to using super without breaking client code that
subclasses).

Well, client classes which are leaves of the class tree can still safely use BaseClass.thisMethod(self, args) -- it's only classes that are written to be extended that must all be converted to using super(). So I'm not sure how you think your clients are breaking.

See the section "Subclasses must use super if their superclasses do". This is particularly a big issue with __init__.


Adding optional arguments to one branch of the inheritance tree, but
not another, or adding different optional args in both branches.
(breaks unless you always pass optional args as keywordargs, and all
methods take **kwargs and pass that on to super).

But that breaks anyway; I don't see how using the old Base.method(self, args) approach makes this easier, *unless* you are using single inheritance. If you're expecting single inheritance anyway, why bother with super()?

There is a distinction between simple multiple inheritance, which did work in the old system vs. multiple inheritance in a diamond structure which did not work in the old system. However, consider something like the following (ignore the Interface/implements bit if you want. It's just to point out a common situation where two classes can independently implement the same method without having a common superclass):


class IFrob(Interface):
  def frob():
    """Frob the knob"""

class A:
  implements(IFrob)
  def frob(self, foo=False):
    print "A.frob(foo=%r)"%foo

class B:
  implements(IFrob)
  def frob(self, bar=False):
    print "B.frob(bar=%r)"%bar

class C(A,B):
  def m(self, foo=False, bar=False):
    A.m(self, foo=foo)
    B.m(self, bar=bar)
    print "C.frob(foo=%r, bar=%r)"%(foo,bar)

Now, how do you write that to use super? Here's what I come up with:

class IFrob(Interface):
  def frob():
    """Frob the knob"""

class A(object):
  implements(IFrob)
  def frob(self, foo=False, *args, **kwargs):
    try:
      f = super(A, self).frob
    except AttributeError:
      pass
    else:
      f(foo=foo, *args, **kwargs)
    print "A.frob(foo=%r)"%foo

class B(object):
  implements(IFrob)
  def frob(self, bar=False, *args, **kwargs):
    try:
      f = super(B, self).frob
    except AttributeError:
      pass
    else:
      f(bar=bar, *args, **kwargs)
    print "B.frob(bar=%r)"%bar

class C(A,B):
  def frob(self, foo=False, bar=False, *args, **kwargs):
    super(C, self).frob(foo, bar, *args, **kwargs)
    print "C.frob(foo=%r, bar=%r)"%(foo,bar)



And using multiple inheritance the old was was not confusing? Surely
you are joking.

It was pretty simple until you start having diamond structures. Then it's complicated. Now, don't get me wrong, I think that MRO-calculating mechanism really is "the right thing", in the abstract. I just think the way it works out as implemented in python is really confusing and it's easy to be worse off with it than without it.


If they're happy with single inheritance, let them use super()
incorrectly. It works, and that's what count. Their code didn't work
right with multiple inheritance before, it still doesn't. Some people
just are uncomfortable with calling Base.method(self, ...) and feel
super is "more correct". Let them.

Their code worked right in M-I without diamonds before. Now it likely doesn't work in M-I at all.


James

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to