
Greg Ewing writes:
If I were teaching a newcomer about super, I wouldn't even tell them that it *has* a class argument. So they wouldn't have any expectation about targeting, because they wouldn't know about it.
I would probably teach newcomers the argumentless form only too. That's all they'll need. But argument or not, they need to know "what" does super proxy, and the simple answer, for a newcomer, is "the parent". If they were to ask me what happens when there's multiple parents, i would definitely have to tell them not to go there, today at least, since today's multiple inheritance is complex. But if there was a way to tell super what class it should be a proxy of, that would be very easy to explain : when there's two parent, just give the parent you want to target as an argument to super.
It's a delicate operation that requires knowing a *lot* about the classes you're blending together. In this case, the fact that both class names have the form <adjective>Gobelin would make me suspect quite strongly that they *do* have some common ancestry.
It requires knowing a *lot* about the classes you're inheriting from, *today*, and that's a problem I'm trying to adress. And you being able to tell those 2 classes have some sort of common ancestry wouldn't be of much help if you don't already know about MRO and the effect it might have on inherited classes in case of multiple inheritance. So you would already need to be quite knowledgable about MRO and multiple inheritance to got the result you expect here. If super were to only target the parents, either the only parent for the argumentless form, or the specified parent in case of MI, this scpeific scenario wouldn't require you to have any extra knowledge on MRO / super / MI. It would already behave exactly like you would expect. Of course there are use cases for super following MRO. Those need to be covered too, and not get rid of. I think the ability of super to handle remaps after MRO injections should be conserved, so the scenarios in which we would pass directly the class we wanna target should allow for remapping of the parents. Not that there's a common use for it, but still. The Mixin use case, where we explicitely use the super ability to side jump so that our mixin 'specialise' the last class in MI order would really benefit from a feature allowing a class to select a parent after being defined. This is the meaning of my adpotion proposal, and i believe this use case to be the most common use case of MI in python. We could actually consider it a case of simple inheritance that didn't say its name. The adoption proposal would convert those MI cases back to SI cases. The diamond problem on its own requires specific attention, as the gobelin exemple i give showcases a case where we would most definitely want the top class to be called every time it appears in the inheritance tree, but there are other cases where we most definitely want the top class to be called only once, case such as ORMs doing commits to databases. My proposal is to implement a way to allow the programmer to decide what strategy fits their needs. the 'use_parent_mro' keyword of super would work nice in today's context, perhaps not so nice assuming all other changes i advocate for passed first. A class decorator / attribute deciding the strategy super should use is an option too. Follow MRO / follow inheritance tree for exemple would be 2 simple options. honestly, idk what design would be the best for this case, all i know is that the solution should allow for multiple strategies. ---- Chris Angelico writes:
I'm curious when you would ever be subclassing something from another library without knowing its hierarchy. This is common in Django.
---- Stephen J. Turnbull writes:
One really plausible example is given in Raymond's piece: a later version of the same library refactors a "monolithic" class as a child of one or more "private" classes that are not intended to be exposed in the public API, but your multiply-derived class *written before the refactoring* Just Works. As far as I can see, super(), and maybe even the deterministic MRO, is needed to make that work. I'm curious about this exemple, do you have a link to share so i could have a look at the code / change in code? This could be a good exercice.