
On Tue, 5 Apr 2022 at 12:37, malmiteria <martin.milon@ensc.fr> wrote:
ROUND 3 i guess
I promised paul moore an up to date proposal, here it is:
1) an alterhitance module, dedicated to all __bases__ (the iterable of parents) alteration operations This replaces the "dependency injection" use case (based on MRO injection, not __bases__ edits), and on its own doesn't need any addition to python itself, however, it relies on today's super ability to handle implicitely remaps of __bases__, and other proposal might remove this capacity, if not accounted for, so i'm leaving this altheritance module in the proposal, just so we all know it's not forgotten about.
If you want to implement a module, do so and put it on PyPI. I personally think this is probably useless, but it's not a Python change so do it if you want. When (if) it's proved useful, if you want to propose it for the stdlib, you can argue for that separately based on the module's popularity.
2) the adoption syntax, for classes that are designed to work with multiple parent (mixin use case) would replace code from: ``` class MyView(LoginMixin, PermissionMixin, View): ... ``` to ``` class MyView( LoginMixin( PermissionMixin( View ) ) ): ... ``` Essentially, it's a way to tell MyView to inherit from LoginMixin, which in this context inherits from PermissionMixin, which in this context inherits from View. Again, this could be talked about in a separate post, but it is relevant to the current discussion, as Mixins are the most current use case for today's ML. Actually, idk, should i make a dedicated post for it? or should i keep it in this thread, as it is relevant to the end goal? It has value on its own tho.
I have no idea what the point of this is. And you've made no attempt to describe use cases that would gain from this, or explain what existing constructs would be improved by it. So -1 from me.
3) Multiple strategies for diamond problems Essentially, in more general terms, how to handle the case of a class appearing multiple time in an inheritance tree, should it be specialised once? each time? only on some specific occasions? I want to add either a decorator, or a class attribute, or anything for that matter, so that the programmers can choose the strat they need. I've got an idea this night about having the kwargs "use_target_MRO" for super, that might cover this need, i'm not sure.
You've not defined this at all, nor have you explained why it's needed. I've never had a "diamond problem" that the existing model didn't suffice for (to be honest, I'm not entirely sure I've ever encountered a diamond problem at all, as I avoid complex multiple inheritance hierarchies because they feel like a code smell anyway). -1 from me.
4) Allowing to pass as argument of super the class you're targeting, which i got the idea this night could be done with a target kwarg. argumentless syntax would behave the same
This is a breaking change (passing an argument to super means something different right now). You need to justify breaking existing code (or demonstrate that no-one currently passes arguments to super()) and you haven't. And even if you avoid *any* breakage, you still need to explain why it's worth doing, which you haven't. So -1 from me.
I believe if all those proposal come first, super is not benefitting from MRO anymore, and MRO could be removed.
super is not the only way the MRO is used. And you can't just "remove" it anyway - methods need to be resolved, you can propose a change to the order, but "removing" any resolution order makes no sense.
5) replacing MRO with a method resolution that I describe at the top of my post: - accessing an attribute / method that multiple parent can provide would raise an ExplicitResolutionRequiredError, those errors can be solved by defining the attribute in the child class, and performing the "merge" as you'd want it there.
So making the programmer do all the work, rather than having a default behaviour that works in at least some cases. That's strictly worse than the current behaviour.
- accessing an attribute that only one parent can provide would work fine, even if multiple parent are present (what matters is the uniqueness of the candidate to resolution)
Same as now
- accessing an attribute that no parent have would raise an AttributeError.
Same as now
- obviously, accessing an attribute defined in the class body would resolve to this attribute
Same as now
- this would apply for attribute and method, just like today's MRO.
So this is essentially making some existing functionality raise an error, without any new functionality. -1 from me.
I personnally have an issue with the fact that today, some class definition are not allowed, because MRO doesn't know how to deal with those scenarios. I'm trying to see if i can come up with a non breaking change alternative, i don't have one for now.
Unfortunately, just the fact that you have an issue with this isn't enough to justify a change. You need to provide objective evidence that convinces others. And so far, after thousands of words of emails, you haven't managed. Maybe it's time to accept that others don't agree?
The value of this proposal is that today's super feature is widely misunderstood, and even considered deceptive by some.
What *evidence* do you have for that? In reality, I think super is only occasionally used, mostly only for straightforward cases, and anyone using anything more than the basics (e.g., calling super() with arguments) is *already* doing something complicated, and should be checking the documentation (because there will be very few examples on the web to copy from, demonstrating it's not common usage).
My proposal is built around the idea of making the most straightforward / least surprises UX for the programmer.
And yet all of the confusion you've generated with these proposals suggests that your ideas are *far* from being "most straightforward / least surprises" :-(
As some of you mentionned, there are questions to be solved before introducing breaking change. As it is, only change 5 would be a breaking change, and previous proposal have values on their own.
Wrong, see above. (4) is also breaking.
I intend this 5 proposal to be produced one by one, not all at once, the order in which i present them is relevant.
I'm perfectly willing to try to produce an implementation to these proposal, run it against a selection of python project, and compare their tests output with / without those change, to measure the amount of code that actually breaks. This would give us a very clear idea of the amount of actual breakings, so we could make a more enlightened decision.
That would be useful evidence (although it will miss any usage in closed source projects, a significant element of Python usage). But simply demonstrating that "breakage is minimal" (assuming that's what you find) is only a small part of the work. Demonstrating relevant real-world use cases that would be improved by your proposed changes is another part. As is describing your proposed model clearly enough to work as documentation, *without* provoking controversy and confusion. You have a long way to go with both of those.
The adoption proposal would require to come first i think, and start getting used by the community, as removing MRO would most definitely make the old syntax break. Other than that, the use cases of ML are very limited today, so i'm not sure what amount of breakings would be reasonable to expect, after spreading of the adoption feature.
Realistically, I'd be surprised if these proposals ever end up getting implemented in Python. I'm probably going to leave this discussion at this point, as I don't see it as going anywhere. Paul