TL;DR:
You know you can call the method on any class you want just by
explicitly writting the class name instead os "super()" don't you?

That said, the current MRO (and super) behavior is what folks arrived at
almost 20 years ago, the "C3 algorithm", in Python 2.3 after a little tweak
from the behavior of new-style classes in Python 2.2.

It is doucmented here - https://www.python.org/download/releases/2.3/mro/
-  and it is the "least surprise" and "most correct" way to do it, as the
document itself explains.

In particular, as it gets to what seems to trouble you - " 4) Multiple
parent : the method / attribute can't be resolved in the class itself, and
can be resolved by at least 2 of its parents, then an
ExplicitResolutionRequired error should be raised" -
that is exactly the point the MRO algorithm kicks in, in a way that
ultimately makes sense to ensure any overridden method in the inheritance
hierarchy is called, most specialized first.


Eventual hierarchies where the rules there won't fit are the cases where
one is free to call whatever method they wish explicitly, as if super never
existed.

On Sat, Mar 26, 2022 at 2:00 PM malmiteria <martin.mi...@ensc.fr> wrote:

> 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?
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/RWAJY7TJETZEWYQJUZURLNMYSEV2TCDL/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DVHRAF3XFM7ODCJHHR7P2OS3D4567OZW/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to