[Python-ideas] mro and super don't feel so pythonic
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 s
[Python-ideas] Re: mro and super don't feel so pythonic
If you want to explicitly delegate a method to a class, you should explicitly delegate a method to a class. This is exactly why a lot of folks feel composition is better than inheritance (at least often so). You don't need `super()` to call `SomeSpecificClass.method(self, other, args)` On Sat, Mar 26, 2022, 12:59 PM malmiteria 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 > -
[Python-ideas] Re: mro and super don't feel so pythonic
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 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 em
[Python-ideas] Re: mro and super don't feel so pythonic
i mean yeah, of course you don't need super. And i also understand that feeling that composition is better than inheritance. But that's beside my point, super acts as a proxy to a parent, and is by default the feature to refer a parent from within a class method. This is the feature that i think is flawed in some ways and i'm trying to produce an alternative to. ___ 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/T47OLTQI7U7CN5WE7KV7ZEWYOHHPZPMX/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Sat, Mar 26, 2022 at 10:24 AM malmiteria wrote: > i mean yeah, of course you don't need super. > And i also understand that feeling that composition is better than > inheritance. > That's a bit beside the point -- we can use inheritance, and also be more explicit about calling superclass methods if need be. > But that's beside my point, super acts as a proxy to a parent, and is by > default the feature to refer a parent from within a class method. > Almost -- I think super() acts a proxy to the *perents*, plural. even if the current class inherits from only one class, that superclass may inherit from more than one class. If you just want the superclass, you can call it directly: class B(A): def some_method(self, ...): A.some_method(self) And if you do that, you will get a good fraction of the behaviour you are expecting. The point of super() is to provide a way to, yes, implicitly, call a method on all the superclasses in the inheritance tree. There's more than one way to do that, but it's perfectly reasonable that Python provide only one way, with clear rules, which is what we have now. And if there's going to be one way, the MRO currently in use is a pretty darn good one. Yes, sometimes the specified MRO isn't what you need -- but It's my impression that your proposal really doesn't add anything over simply calling superclasses directly the way you want. But if you want to show how useful it could be, then go ahead and continue working on your prototype,and share it with the world. If people find it useful, then maybe it would be worth considering as a addition to Python. NOTE: I would work hard to find real examples where you can show how the current super() doesn't work well, and how explicitly calling superclass methods is substantially uglier than using your parent() approach. -CHB -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ 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/Z3DP5GA2CYHFI4OLJKWBMG4HOU754QV2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
I'm aware that 'class.method' works, but this doesn't give the same proxy feature super does. But in essence, i disagree it's the most correct way to do it. I think it's very likely the most correct *automatic* way of doing it tho. And that's my point, why does it have to be automatic? Also, it doesn't ultimately make sense to order an inheritance tree, as much as it doesn't make sense to order left and right when you're going up and down, that's simply another dimension of your problem. But assuming it make sense (i'm not blind to the sense it makes, i'm just arguing my point), why would this order be the specialisation order? a child is more specialized than it's parent, of course, but one parent is more than the other? why would it be? and i mean, that's not the idea that most people have when they do multiple inheritence, if they think one is more specialized than the other, they make one inherit from the other, they don't set them both as parent of a third. Tho, to make it clear, i've no doubt it's doable without super today. My point is that MRO as it is, has some flaws. Also, Eventual hierarchy where the rule won't fit are simply not allowed today, no matter your use of super. take this one for example : ``` class A(X, Y): pass class B(Y, X): pass class C(A, B): pass ``` This code fails, you can overcome it through composition, but nevertheless, this doesn't justify this problem. Essentially it's a case of "this is broken, but something else close enough isn't". It works, but it's still broken Oh and just to make it more explicit, MRO and super are two different concern of mine here. They could be addressed separately, but since those feature are related, i felt like sharing it in one post ___ 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/NH5JOZUHEN7TPNCFDQKJXFJHXQL6MTI2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
the alternative to super really is not the important part of my proposal, it's the alternative to MRO. An example of a case where i genuinly believe my solution adds value is this : ``` class A: def method(self): print("A") class B: def method(self): print("B") class C(A, B): pass ``` Today, a code such as ```C().method()``` works without any problems except of course when the method you wanted to refer to was the method from B. If class A and B both come from libraries you don't own, and for some reason have each a method named the same (named run, for example) the run method of C is silently ignoring the run method of B. I believe it would make the programmers life easier to have an error at this time, or anything tbh, to make explicit this resolution, because it really is not explicit from most programmers perspective my alternative to super comes to fit the alternative to mro, i think it stills matter to have a dedicated feature instead of simply calling class.method, this allows for more error handling and stuff like that, in case for example you're calling super on a class that's not a parent for example, since super really is for accessing parents context. This is not so much about final code, but more about making it easier *when* writing code. But the final code would definitely not look that much prettier / ugglier, I agree And finally, super is not a proxy to parents, even plural, it's a proxy to the next in mro order. in this case : class Top: def method(self): print('Top') class Left(Top): def method(self): print('Left') super().method() class Right(Top): def method(self): print('Right') super().method() class Bottom(Left, Right): def method(self): print('Bottom') super().method() Bottom().super() would print "Bottom", "Left", "Right", "Top". super, in Left, reffers to Right, which is not a parent of Left (and is completely absent of it's definition) Anyways, i'm called to a pub, i'll talk to you guys more tomorrow, have a great night ___ 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/EWMRM6HIDK4XJPEV7R3WETVP72SUT4RA/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On 2022-03-26 11:15, malmiteria wrote: the alternative to super really is not the important part of my proposal, it's the alternative to MRO. An example of a case where i genuinly believe my solution adds value is this : ``` class A: def method(self): print("A") class B: def method(self): print("B") class C(A, B): pass ``` Today, a code such as ```C().method()``` works without any problems except of course when the method you wanted to refer to was the method from B. But that's what people have been saying: if you want to call the method from B, just call the method from B. If class A and B both come from libraries you don't own, and for some reason have each a method named the same (named run, for example) the run method of C is silently ignoring the run method of B. I believe it would make the programmers life easier to have an error at this time, or anything tbh, to make explicit this resolution, because it really is not explicit from most programmers perspective To me it doesn't seem reasonable that someone would inherit from two classes and want to call a method from one without even knowing that there's a method name collision. If you're going to inherit from A and B, you need to know what methods they provide and you need to think about the order you inherit in. If you inherit from two classes that have a name collision because they provide unrelated methods that happen to share a name, I think you have a problem right there that needs to be resolved (like by having the inheriting class explicitly delegate to a specific superclass). But I don't think that is a very common situation. Based on your example, I still don't really see the advantage of your proposal. Currently super is the way to say "let Python choose for me what method implementation to call next, based on the class hierarchy". You seem to be saying that in some cases that won't call the right thing so you don't want it to call anything. But if super doesn't call the right thing, you can just not use super and instead explicitly call the method you want, so I don't get what this proposal gains. -- Brendan Barnwell "Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail." --author unknown ___ 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/ARY3TTP2RVB6G5NFAF2UJRKWRNAQIC7T/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On 3/26/22 09:57, malmiteria wrote: > 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. When I first started using Python I also didn't like super() and the mro. However, at some point it dawned on me that subclassing is not a trivial task -- you don't just get a new class with some neat behavior from another class -- what you get is the original class, plus some neat behavior from the new class. In other words, subclassing is a very tight coupling of code, and you had better know the classes you are inheriting from to get it right -- and that part is the programmer's responsibility, not Python's. To use your `run()` example: class A: def run(self): print('A') class B: def run(self): print('B') class Z(A, B): def run(self): # make the programmer choose raise RuntimeError("call to `run()` not allowed, choose `run_a()` or `run_b()`") def run_a(self): return A.run() def run_b(self): return B.run() -- ~Ethan~ ___ 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/EVCUL3PVRIDAMMRYGU56J4AK4ZBRNM64/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On 3/26/22 12:04, Ethan Furman wrote: > On 3/26/22 09:57, malmiteria wrote: > >> 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. > > [...] In other words, subclassing is a very tight coupling of code, and you had better know > the classes you are inheriting from to get it right -- and that part is the programmer's > responsibility, not Python's. To add to that, you can write your custom metaclass, or even (and more easily) a class decorator, that goes through the mro and raises an exception if there are any duplicate methods in previous classes that have not been overridden in the new class. -- ~Ethan~ ___ 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/VIWNDPEHPD2BO7S7YHQTPPK2QBOPQH5Z/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
Agreed w/r/t the issue of typing, glad I wasn't the only one who was feeling that way. Maybe a reasonable approach would be to potentially add this as an option to the collections module? Either as an isolated function (`anamedtuple` perhaps) or add control flow to `namedtuple` such that when only kwargs are provided, return an anonymous namedtuple directly. Or both? :shrug: Id want to try to do most of the work via the C/Python API, my original `def` is on par with calling an instance of `namedtuple`, but both are an order of magnitude slower than simply creating a tuple, which I think is unacceptable as a construct that I would want to use extensively in a codebase. Hell, even instantiating a generic object is twice as fast. If I wanted to submit this as a pep (or even just submit this for a potential sponsorship), is the best way to go about it to work directly in a clone of the c/python repo, or to write a standalone library first and then after preliminary approval, add it to c/python? ___ 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/Q6JTO37I42OKOAIJVBD63UL5QO3KEYLI/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Sat, Mar 26, 2022 at 10:50 AM malmiteria wrote: > why does it have to be automatic? > because that's the entire point of super() -- if you don't want automatic, do what you want by making direct method calls. > if they think one is more specialized than the other, they make one > inherit from the other, they don't set them both as parent of a third. > I think the best use case for multiple inheritance is mixins -- which do have a natural order -- as you say, in other cases, you can do single inheritance. > Tho, to make it clear, i've no doubt it's doable without super today. My > point is that MRO as it is, has some flaws. > Also, super() actually calls the method on all the superclasses (but not the same one twice) -- so that right to left thing doesn't matter. It does matter with regular calling of methods, though, but you need SOME rule there. -CHB > Also, Eventual hierarchy where the rule won't fit are simply not allowed > today, no matter your use of super. > take this one for example : > ``` > class A(X, Y): pass > class B(Y, X): pass > class C(A, B): pass > ``` > > This code fails, you can overcome it through composition, but > nevertheless, this doesn't justify this problem. > Essentially it's a case of "this is broken, but something else close > enough isn't". It works, but it's still broken > > > Oh and just to make it more explicit, MRO and super are two different > concern of mine here. They could be addressed separately, but since those > feature are related, i felt like sharing it in one post > ___ > 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/NH5JOZUHEN7TPNCFDQKJXFJHXQL6MTI2/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ 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/OJWW37W6QV326NRAXHEO3PMG53D35JUZ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Anonymous namedtuples, revisited
> If I wanted to submit this as a pep (or even just submit this for a > potential sponsorship), is the best way to go about it to work directly in > a clone of the c/python repo, or to write a standalone library first and > then after preliminary approval, add it to c/python? You don’t need an implementation to write a PEP, and certainly not to get a sponsor. That being said, a prototype can be helpful to work out the issues. You could go either way, but if it can be stand-alone, that’s easier, especially for others to try it out. -CHB > ___ > 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/Q6JTO37I42OKOAIJVBD63UL5QO3KEYLI/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ 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/3C4USZ57YI4BY2WX4ZAQ33BZG3BZ2RLP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Sat, Mar 26, 2022 at 10:40:45AM -0700, Christopher Barker wrote: > Almost -- I think super() acts a proxy to the *perents*, plural. Correct. In general, classes do not have a parent. They have one or more parents, each of which in turn can have one or more parents. Anyone talking about the "parent" or "base class" of a generic, unspecified Python class is stuck in a single inheritance world. Years ago, James Knight wrote a provocatively titled blog post called "super considered harmful". https://fuhm.net/super-harmful/ After much discussion on one of the Python lists, I think it was Python-Dev, he backed down somewhat and admitted that actually yes, super is great, "but you can't use it." Except of course thousands of people do use it. And it works. > If you just want the superclass, you can call it directly: > > class B(A): > def some_method(self, ...): > A.some_method(self) Please please please don't do that! That just needlessly breaks multiple inheritance, and for no good purpose. Just use super(), even for single inheritance. Anyone who hasn't read Raymond Hettinger's "super considered super", please do. https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ > The point of super() is to provide a way to, yes, implicitly, call a method > on all the superclasses in the inheritance tree. No, it is not implicit. Please don't repeat that mistake. `super().some_method(self)` is perfectly explicit. It is just that the specific class used is computed at runtime, not hard-coded. We wouldn't say that get_parent().some_method(self) is "implicit" because the parent is computed at runtime. We should stop saying that super() is "implicit". It is not. It is an explicit call to resolve the mro and call some_method on the appropriate parent. The only "implicit" part of super is that it implicitly knows the current context. But that's not a point against it. Nobody complains that functions "implicitly" know their global environment, and therefore name resolution in functions is broken due to implicitness: # thismodule.py def func(): return "something" def main(): return func() # Oh no, it is "implicit"! # should write: return thismodule.func() # Much more explicit!!! Despite what the Zen says, sometimes a modicum of implicit knowledge is worth an imperial ton of explicit verbosity. And the zero-argument form of super() is one of those times. > There's more than one way > to do that, but it's perfectly reasonable that Python provide only one way, > with clear rules, which is what we have now. And if there's going to be one > way, the MRO currently in use is a pretty darn good one. The C3 linearization used by Python is provably correct. I am not aware of any other non-broken linearization algorithms for multiple inheritance. Perhaps they exist; perhaps not. Before we had C3, the ways multiple inheritance was resolved in Python 1.x through 2.2 was broken. Note carefully that we had **two** ways of resolving multiple inheritance, for classic classes and new-style classes, and both were broken in different ways, until we moved to a proven algorithm in Python 2.3. https://www.python.org/download/releases/2.3/mro/ -- Steve ___ 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/6SQARR4S4FPOHOKWAF7NUY6HDVLCBKHB/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Sat, Mar 26, 2022 at 05:49:41PM -, malmiteria wrote: > Also, Eventual hierarchy where the rule won't fit are simply not > allowed today, no matter your use of super. > take this one for example : > ``` > class A(X, Y): pass > class B(Y, X): pass > class C(A, B): pass > ``` Because that is an inconsistent hierarchy, which makes the code broken, and leads to bugs. Both Python 1.x "classic classes" and Python 2.2 new-style classes allowed that, even though it is broken. However it is not *obviously* broken. Your classes need methods that actually do some work to see the breakage. See https://www.python.org/download/releases/2.3/mro/ for details. -- Steve ___ 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/PVVTR4Z2A4ORYC33X4GKREYITFZNLDTI/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Sat, Mar 26, 2022 at 06:15:57PM -, malmiteria wrote: > class C(A, B): > pass > ``` > > Today, a code such as ```C().method()``` works without any problems Actually, no, it does not. Only the A.method() runs, because A was not designed for multiple-inheritance. C inherits from both A and B, but only calls one of the methods. > except of course when the method you wanted to refer to was the method from B. Why are you inheriting from A if you don't want to inherit from A? > If class A and B both come from libraries you don't own, and for some > reason have each a method named the same (named run, for example) the > run method of C is silently ignoring the run method of B. Right. Multiple inheritence in Python is **cooperative** -- all of the classes in question have to work together. If they don't, as A and B don't, bad things happen. You can't just inherit from arbitrary classes that don't work together. "Uncooperative multiple inheritance" is an unsolvable problem, and is best refactored using composition instead. -- Steve ___ 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/HVATCZIKQ642LF7IIB76S67EY3FVOLMV/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Sat, Mar 26, 2022 at 11:16 AM malmiteria wrote: > the alternative to super really is not the important part of my proposal, > it's the alternative to MRO. > wait, what? We may need some more clarity as to what you are after. You need SOME method resolution order, and Python's MRO is pretty simple and straight froward. > ``` > class A: > def method(self): > print("A") > > class B: > def method(self): > print("B") > > class C(A, B): > pass > ``` Today, a code such as ```C().method()``` works without any problems > except of course when the method you wanted to refer to was the method > from B. > If class A and B both come from libraries you don't own, and for some > reason have each a method named the same (named run, for example) > the run method of C is silently ignoring the run method of B. > But the author of C should certainly test that, and choose what order to put them in. It's possible they would want one method from A, and one from B, but then they could override those methods if they need to. I'm not sure how you could be more explicit than that. I believe it would make the programmers life easier to have an error at > this time, or anything tbh, to make explicit this resolution, because it > really is not explicit from most programmers perspective > But much (most) if the time — you want either to call all of the superclasses parent methods (super()) or one of them (the usual direct call) - it would be not very helpful, and quite annoying to get errors when I explicitly told Python what I want to do. in case for example you're calling super on a class that's not a parent > for example, I don’t think that’s even possible. > but more about making it easier *when* writing code. Even a tiny modicum of testing would take care of that. And finally, super is not a proxy to parents, even plural, it's a proxy to > the next in mro order. It’s a proxy to all of the classes in the MRO, which is the parents. in this case : > class Top: > def method(self): > print('Top') > class Left(Top): > def method(self): > print('Left') > super().method() > class Right(Top): > def method(self): > print('Right') > super().method() > class Bottom(Left, Right): > def method(self): > print('Bottom') > super().method() > > Bottom().super() would print "Bottom", "Left", "Right", "Top". > super, in Left, reffers to Right, which is not a parent of Left (and is > completely absent of it's definition) Which is we what I mean by all of them. If you didn’t use super in the whole chain— it would stop when it found the method. If you do, then they are all calked, and each one only once. Steven A mentioned the two seminal articles “super considered harmful” and “super considered helpful” — the thing is, they both say the same thing— in order for super() to work you have to follow certain rules. And then it works predictably. Whether that’s helpful or not depends on your use case. -CHB -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ 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/HHRT756JUXOFBTVV4RZ7FUTVW42VE2IM/ Code of Conduct: http://python.org/psf/codeofconduct/