New submission from malmiteria <martin.mi...@ensc.fr>:

Hi,

Before anything, i made a github repository about this topic here : 
https://github.com/malmiteria/super-alternative-to-super

The core of what i wanna discuss here is that i don't think mro and super 
(mainly because it relies on mro) are very pythonic. Mainly that some behaviors 
of the mro are too implicit, and are silencing what really should be errors.



Let me explain :
in case of multiple inheritence, resolving a child method from it's parent 
isn't an obvious task, and mro comes as a solution to that. However, i don't 
understand why we don't let the programmer solve it. I think this is similar to 
a merge conflict, and not letting the programmer resolve the conflict feels 
like silencing an error. This is especially infuriating when you realise that 
mro doesn't solve all possible scenarios, and then, simply refuses the 
opportunity to solve it to the programmer.
Then, super relying on mro gives off some weird behaviors, mainly, it's 
possible for a child definition to affect what a call to super means in it's 
parent. This feels like a side effect (which is the 'too implicit' thing i 
refer to).
I also don't understand why we can't simply pass the parent targeted as 
argument to super, instead of having no argument, or having to pass the current 
class and instances as argument :
super(child) is a proxy to parent, when super(parent) would make more sense to 
be the proxy to parent, in my mind.

I dive in more depths about those topics in the readme of the github repository 
i linked at the top of this comment.



what i propose is a solution that would follow those rules:

The mro alternative, which i called explicit method resolution aka EMR (which 
is probably not a good name since i apply it, as mro, to all class attributes), 
follow those rules :
 1) Straightforward case : the class definition has the method / attribute : 
this is the one EMR should resolve to
 2) Not found : the method / attribute can't be resolved in the class itself, 
or by any of it's parents, then it should raise an AttributeError
 3) Only on parent : the method / attribute can't be resolved in the class 
itself, and can only be resolved by one of it's parents, this is the one EMR 
should resolve to
 4) Multiple parent : the method / attribute can't be resolved in the class 
itself, and can be resolved by at least 2 of it's parents, then an 
ExplicitResolutionRequired error should be raised
 5) Transimittin errors : the method / attribute can't be resolved in the class 
itself, and one parent at least raises an ExplicitResolutionRequired error, 
then it should raise an ExplicitResolutionRequired error
 6) (optional?) Single source : when multiple parent can resolve a method from 
a single source (in case of diamond shape inheritence), the 
ExplicitResolutionRequired  is not needed

The super alternative, which i called __as_parent__ should follow those rules :
 1) reliability : the target __as_parent__ points to should not depend on 
anything other than the argument passed to it
 2) expliciteness : in case of multiple inheritence, the parent targetted 
should be passed as an argument to the __as_parent__ method.
 3) impliciteness : in case of simple inheritence, it is not needed to specify 
the parent targeted (since there can only be one, and it make it closer to the 
actual behavior of super in most cases)
 4) ancestors as targets : should be able to target ancestors, either direct or 
not (which is needed in case two grandparent define a method that a single 
parent share, there would be no other way to solve the 
ExplicitResolutionRequired otherwise)



this solution has a few advantages in my mind :
 - the current mro and super are more tightly coupled than the emr and 
__as_parent__ i propose here
 - the __as_parent__ is more reliable than super in its behavior, and should 
lead to an easier learning curve
 - the emr i propose as a replacement to mro allows for some inheritence tree 
mro doesn't allow.
 - the __as_parent__ method being able to target specific parent allows for 
different methods to visit the parents in different order easily, which today 
would be harder, since the parent visiting order is tightly coupled to the 
class definition
 - with emr, in case of problematic resolution, an error is raised to tell you 
about the problem, and ask you for explicit resolution, the current solution 
doesn't, which can lead to surprises closer to production environment.



A few possible downsides :
 - the transition would be a pain to deal with
 - the current mro allows for dependencies injection in the inheritence tree. I 
believe this feature should be untied from super and mro, but it would require 
some work.
 - the current super and mro are old enough to have been faced with issues and 
having been updated to solve those issues down the line. Any alternative would 
have to face those issues again and new ones down the line
 - any coexistence between those two solution would require some work to make 
sure they don't break one another (i've explored some of those scenarios in my 
repository, but i definitely didn't cover it all)


I believe that what i talk about here is definitely too much at once.
For exemple, adding a kwarg to super to specify the parent it targets would be 
a very easy change to add into python, and wouldn't require much more of what i 
talk about here, but it would still have some of the value i talk about here.
But overall, it all makes sense to me, and i wanted to share it all with you 
guys.

What do you think? does it makes sense? Am i missing something?

----------
messages: 416071
nosy: malmiteria
priority: normal
severity: normal
status: open
title: mro and super don't feel so pythonic
type: enhancement

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue47130>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to