
On Tue, 29 Mar 2022 at 07:39, malmiteria <martin.milon@ensc.fr> wrote:
Chris Angelico writes:
I'm not sure what you DO expect, though.
in this case : ``` class A: def method(self): pass
class B: def method(self): pass
class C(A,B): pass ```
it is unclear what C().method should resolve to. So instead of forcing a resolution, i'd prefer an error to be raised, stating that the resolution can't be done automatically. Hence the name ExplicitResolutionRequired.
This is what i would expect from calling C().method in this example. Or at least, this is how my solution would behave.
Please, can we get a non-toy example? I look at this example and go "of course it should resolve to A.method", but that's because, with these names, there is absolutely no clue as to your intention. The only thing I have to go on is the code itself, and to my mind, there are two equally plausible options: either the first one named takes precedence, or both methods should be called. Python chose one of those options. Other languages have chosen the other. But with nothing to go on but the code, all I can say is: the current behaviour looks perfectly fine to me.
Which of these super() calls would, by your description, need to raise an error?
None, actually. super should not raise the ExplicitResolutionRequired error, never. Accessing a method from a child class, which don't redefine it, when multiple parent have it, should raise the error.
Sure, but whatever. Whether it's the super call itself or the attribute lookup on the super object, which ones need to raise? And once again, you're just giving us toy examples with names that tell us nothing. Please, real examples. Show us how this is actually useful.
Updating C's code like that : ``` class C(A,B): def method(self): self.__as_parent__(A).method() # calls method defined in A self.__as_parent__(B).method() # calls method defined in B ```
now running ```C().method``` works fine.
The trouble is, if I now create these: class D(B): pass class E(C, D): pass then C's methods should be delegating to D and not to B. That's a fundamental problem for any sort of explicit lookup. Also, how is this different from simply writing: class C(A, B): def method(self): A.method(self) B.method(self) ? If you're going to explicitly call for a particular parent, why not just do that?
Note that with the use of super, you can't tell in the body of the C method how to combine A and B's methods. You have to rely on super order of visiting those methods. Meaning that in this specific example you'd need either to add a call to super in A, for it to call B's method, or a call to super(A, self) in C for it to call B's method, without having to change A's definition.
Yes. That's intentional. Usually, that is a deliberate and desired feature.
It's far less obvious than you perhaps think, so please elaborate, please show exactly what constitutes an error. I apologise if i wasn't clear, i hope it's better now. I'll do my best to explicit my idea more in the future too.
Unfortunately, no, it's not. With names like A, B, and C, we have to figure out our own purpose behind things, and I've spent so much time with Python's existing system that everything seems fine to me. You'll need to show exactly what doesn't work with the current system, instead of assuming that we understand the problem. Real example.
"class C(B1, A, B2)", you could have some parts of what's currently in B happen before A, and other parts happen after A.
You can't always break a class down, especially when you import those class from a library.
Again, real example please.
The fact that the current super + MRO make it the norm to simply chop off the behavior of class B's method parent call to replace it by C's method behavior is literraly insane to me.
In what world extending a parent method means replacing part of it with some of another parent?
Well....... generally, since Python doesn't allow you to call two functions at the same time, the *only* way to extend a parent method is to replace *all* of it. To replace part of it, you replace all of it and then call the other function, That's precisely what super().method() lets you do. So.... what you call "literally insane", I call "a perfectly normal feature". Hence, again, the need to see what you're actually trying to accomplish - not "replace the MRO", but what you're really trying to do with your code. Take a step back and show us your actual goals, because we cannot see the problems the way you see them. ChrisA