On Wed, 5 Jan 2005 18:00:38 -0500, James Y Knight <[EMAIL PROTECTED]> wrote:
> 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__.

I see. I was thinking about subclassing a single class, you are
talking about subclassing multiple bases. Subclassing two or more
classes is *always* very subtle. Before 2.2 and super(), the only sane
way to do that was to have all except one base class be written as a
mix-in class for a specific base class (or family of base classes).

The idea of calling both __init__ methods doesn't work if there's a
diamond; if there *is* a diamond (or could be one), using super() is
the only sane solution.

> >> 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

Barely; see above.

> 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):
[I presume you meant from instead of m here]
>      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?

The problem isn't in super(), the problem is that the classes A and B
aren't written cooperatively, so attempting to combine them using
multiple inheritance is asking for trouble. You'd be better off making
C a container class that has separate A and B instances.

> > 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.

So then don't use it. You couldn't have diamonds at all before 2.2.
With *care* and *understanding* you can do the right thing in 2.2 and
beyond.

I'm getting tired of super() being blamed for the problems inherent to
cooperative multiple inheritance. super() is the tool that you need to
solve a hairy problem; but don't blame super() for the problem's
hairiness.

> > 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.

If you have a framework with classes written using the old paradigm
that a subclass must call the __init__ (or frob) method of each of its
superclasses, you can't change your framework to use super() instead
while maintaining backwards compatibility. If you didn't realize that
before you made the change and then got bitten by it, tough.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
_______________________________________________
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