[Python-ideas] Re: Conditions for a coherent MI relationship [was Re: Re: mro and super don't feel so pythonic]
On Sat, 16 Apr 2022 at 14:25, Steven D'Aprano wrote: > > On Sat, Apr 16, 2022 at 11:07:00AM +1000, Chris Angelico wrote: > > > On Sat, 16 Apr 2022 at 11:00, Steven D'Aprano wrote: > > > > and therefore > > > > would become the only thing that offers "full MI", displacing other > > > > languages. It's a meaningless concept, unless there is some form of > > > > absolute completeness that can be attained > > > > > > Well duh Chris, sometimes I wonder if you read my posts before jumping > > > in to disagree with me, that is *exactly* what I am arguing. > > > > You placed a LOT of caveats on it. I don't count that as "absolute > > completeness". It is the most complete that YOU, right now, think > > could ever be possible. > > Which conditions would you drop? There's not that many, really. Five. > Six if you include the "no cycles" requirement for the DAG, which I > think is so obviously necessary that it is barely worth mentioning. This is *exactly* the "no true Scotsman" fallacy: you have already excluded from consideration anything that drops a condition you didn't already drop. On the assumption that your five conditions are essential, there's no way that you can drop any of the five conditions and still have it count, therefore the five conditions are essential. Your logic is circular. It is highly arrogant to assume that nobody will ever find a way to implement MI while dropping one of your conditions. They're not fundamental to the definition, they're fundamental to *the way Python does things*. > The most subjective is the requirement for automatic conflict > resolution. It is a legitimate design choice to give up automatic > conflict resolution (that's what C++ and Eiffel do) but that would be a > breaking change for Python. Yes. A breaking change FOR PYTHON. > So come on Chris, back up your disagreement with something objective, > not just wishy-washy "anything might happen in the future!" nonsense. Yet you're willing to argue that other languages don't do "full MI" because they do things that would be a breaking change for Python? > No, not everything is possible. We're never going to discover a new odd > number between 3 and 5, or that 7 isn't really prime, or that cats are > actually a type of plant, or that Australia doesn't exist. You would be very surprised what people HAVE discovered. For instance, it's very common to define the distance between two numbers by subtracting one from the other, but that isn't the only internally-consistent definition of distance that could be used. The only things that we can completely rule out are those which are true by definition, or can be proven mathematically or logically. A new odd number between 3 and 5 is provably impossible. 7 is truly prime, by the definition of primes, and any extension to that definition (eg complex primes or Gaussian integers) must maintain that. Discovering that Australia doesn't exist would be world news, but might indicate that we'd finally angered some nuclear country enough to get ourselves completely blown off the map. (Yeah, I know countries like Russia and the US don't have enough nukes to do that, but we have no idea what sort of arsenal Ghandi is hiding, just waiting for his stats to become negative...) > So be concrete: which of my preconditions do you want to challenge? > > - The inheritance model automatically resolves conflicts. > > As I said, it is a legitimate design choice to give that up, but it > would be a breaking change for Python so we can rule it out. > > In any case, languages without automatic conflict resolution do less > than languages with them. (That might be a good thing.) This is the essence of the "no true Scotsman" fallacy: you assume that it's not true MI without automatic conflict resolution. > - The MRO is entirely dependendent on the shape of the inheritance > graph, and not on incidental properties like the name of classes. > > Let's hear your justification for why breaking that condition is good. > > "I changed my class name from Spam to Eggs, and suddenly the inheritance > relationships between my classes changed." > > "That's not a bug, that's a feature!!!" Is it not true MI if the relationships change? Is that what you're saying? What is "full MI"? > - the inheritance model is consistent, monotonic and preserves local > precedence order (C3 linearization). > > Which of those three will you give up, and why is that a good thing? > > "In my class Spam, superclass A takes precedence over B, but when I > subclass Spam, the precedence swaps and B comes before A." > > "That's not a bug, that's a feature!!!" You keep asserting that, because something OBVIOUSLY would be a bad thing for Python, it must not be "true multiple inheritance". That's why you're being called out for the NTS fallacy. Your entire definition of "full MI" is "Python 2.3+". > > > If you exclude models of MI which are logically incoherent and > > > inconsistent, (such as Python's prior to version 2.3), th
[Python-ideas] Re: Subclassing and inheritance [was Re: Re: mro and super don't feel so pythonic]
On Sat, 16 Apr 2022 at 14:33, Steven D'Aprano wrote: > > On Sat, Apr 16, 2022 at 11:07:00AM +1000, Chris Angelico wrote: > > > > > My view: If a class inherits two parents, in any meaning of the word > > > > "inherits" that follows the normal expectation that a subclass IS an > > > > instance of its parent class(es), then it's MI. > > > > > > Inheritance and "is-a" relationships are independent. > > > > > > In some languages (but not Python), mixins provide inheritance but not > > > an "is-a" relationship. In Python, virtual subclassing provides "is-a" > > > without inheritance. > > > > Virtual subclassing is still subclassing, just implemented > > differently. > > You are correct that virtual subclassing is still subclassing, but it > doesn't provide inheritance. > > >>> from abc import ABC > >>> class Parrot(ABC): > ... def speak(self): > ... print("Polly wants a cracker!") > ... > >>> @Parrot.register > ... class Norwegian_Blue: > ... pass > ... > >>> bird = Norwegian_Blue() > >>> isinstance(bird, Parrot) > True > >>> bird.speak() > Traceback (most recent call last): > File "", line 1, in > AttributeError: 'Norwegian_Blue' object has no attribute 'speak' Yes. I would have to call this an abuse of a feature - you're registering that a Norwegian Blue is a Parrot, without it being able to do anything that a parrot should be able to. (Which I presume was your intention, given your choice of examples.) You can claim that it's a parrot all you like, and Python will happily reflect your declaration when you ask if it's a parrot, but it's a pathological case. It's like designing a class with no __str__ method, or one where __add__ takes three parameters, or in any other way violates normal expectations; you can use perfectly normal inheritance to derive from object, but then you make changes so it no longer "behaves-like-a", ie it violates Liskov. > > What is "inheritance" if it isn't that is-a relationship? How do you > > distinguish inheritance from delegation? > > Haven't you spent all of this thread quite happily distinguishing > between using inheritance and composition/delegation until now? Okay. Yes. I am asking you to now define the difference. My understanding was that inheritance was defined by the "is-a" relationship, and delegation was defined by other things. Now that you're claiming that inheritance is NOT defined by an is-a, I want you to define it. > Subclassing is, as you say, an "is-a" relationship. Whether you use > virtual subclassing or actual subclassing, if you can say: > > issubclass(Norwegian_Blue, Parrot) > isinstance(Norwegian_Blue(), Parrot) > > and get True for both of them, then Norwegian_Blue "is-a" Parrot. > > (Note that there is a technical difference between subclass and subtype, > which I don't think is relevent to Python, but let's not go there.) > > Inheritance is a mechanism where a "child object" automatically acquires > the properties and behaviors of some "parent object". In Python, that is > handled by the interpreter when the child subclasses from the parent > (but not in virtual subclassing). > > The critical thing is that in the absense of overloading or overriding, > calling Norwegian_Blue().speak() will inherit the method defined in > Parrot. We get that inheritance from real, but not virtual, subclassing. Is it still inheritance if there needs to be a boatload of code to make this happen? Because SOM/CORBA and the IDL want to have a word with you. In a good high-level language, there should normally be a convenient way to do this without too much effort. But is that really essential to it being inheritance? As another example: In C++, a function accepting a pointer to a base class can be given a parameter that points to a subclass. In the case of multiple inheritance, this can actually mean that the pointer has to change. So, two questions: (1) Is the fact that a function, not defined outside in the class at all, accepts a pointer, part of the behaviour of the class? And (2) If the compiler has to know "to turn a pointer-to-X into a pointer-to-Y, add an offset of 16", is it still retaining functionality? You make a *lot* of assumptions based on Python, which simply don't hold up in other languages, and then you assert that this is some kind of absolute completeness. > Composition provides a "has-a" relationship. For the sake of brevity, in > simple terms (which may not be completely accurate, please don't nit- > pick just for the sake of nit-picking), we use composition when we > write: > > class Car: > def __init__(self): > self.engine = Engine() > > In this example, Cars are not Engines, but they have an Engine. Hence > composition. > > Delegation provides a mechanism of code-sharing separate from > inheritance, and often used instead of inheritance, or to compliment it. > One object delegates to another object if the first explicitly calls the > second: > > # self is a Car instance. > self
[Python-ideas] Re: mro and super don't feel so pythonic
On 16/04/22 12:56 pm, Steven D'Aprano wrote: If you exclude models of MI which are logically incoherent and inconsistent, (such as Python's prior to version 2.3), then Python's model of MI is objectively as complete as you can get. You seem to be assuming that "full MI" has to include a fully automatic means of method resolution. There's nothing incoherent or inconsistent about the way C++ and Eiffel do MI. The main difference is that they require you to explicitly resolve conflicts between inherited methods -- which is arguably more Pythonic than Python, since they refuse the temptation to guess. -- Greg ___ 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/J5I3MLGZPMOKBRTPANQIE74RMRSHUBJM/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On 15/04/22 10:37 pm, Steven D'Aprano wrote: If you look at languages that implement MI, and pick the implementations which allow it with the fewest restrictions, then that is "full MI". I believe that Python (and other languages) allow MI with the smallest set of restrictions, namely that there is a C3 linearization possible But before Python adopted the C3 algorithm, it was less restrictive about the inheritance graph. So by your definition, current Python does not do full MI! If you have to manually call a specific method, as shown here: https://devblogs.microsoft.com/oldnewthing/20210813-05/?p=105554 you're no longer using inheritance, you're doing delegation. You could also say that Python automatically delegates to the first method found by searching the MRO. Why is one of these delegation and not the other? -- Greg ___ 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/GJIZENRGIZCDPLXPXQ6MBYKEUR33ZGV5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Subclassing and inheritance [was Re: Re: mro and super don't feel so pythonic]
On Sat, Apr 16, 2022 at 11:07:00AM +1000, Chris Angelico wrote: > > > My view: If a class inherits two parents, in any meaning of the word > > > "inherits" that follows the normal expectation that a subclass IS an > > > instance of its parent class(es), then it's MI. > > > > Inheritance and "is-a" relationships are independent. > > > > In some languages (but not Python), mixins provide inheritance but not > > an "is-a" relationship. In Python, virtual subclassing provides "is-a" > > without inheritance. > > Virtual subclassing is still subclassing, just implemented > differently. You are correct that virtual subclassing is still subclassing, but it doesn't provide inheritance. >>> from abc import ABC >>> class Parrot(ABC): ... def speak(self): ... print("Polly wants a cracker!") ... >>> @Parrot.register ... class Norwegian_Blue: ... pass ... >>> bird = Norwegian_Blue() >>> isinstance(bird, Parrot) True >>> bird.speak() Traceback (most recent call last): File "", line 1, in AttributeError: 'Norwegian_Blue' object has no attribute 'speak' > What is "inheritance" if it isn't that is-a relationship? How do you > distinguish inheritance from delegation? Haven't you spent all of this thread quite happily distinguishing between using inheritance and composition/delegation until now? Okay. Subclassing is, as you say, an "is-a" relationship. Whether you use virtual subclassing or actual subclassing, if you can say: issubclass(Norwegian_Blue, Parrot) isinstance(Norwegian_Blue(), Parrot) and get True for both of them, then Norwegian_Blue "is-a" Parrot. (Note that there is a technical difference between subclass and subtype, which I don't think is relevent to Python, but let's not go there.) Inheritance is a mechanism where a "child object" automatically acquires the properties and behaviors of some "parent object". In Python, that is handled by the interpreter when the child subclasses from the parent (but not in virtual subclassing). The critical thing is that in the absense of overloading or overriding, calling Norwegian_Blue().speak() will inherit the method defined in Parrot. We get that inheritance from real, but not virtual, subclassing. Composition provides a "has-a" relationship. For the sake of brevity, in simple terms (which may not be completely accurate, please don't nit- pick just for the sake of nit-picking), we use composition when we write: class Car: def __init__(self): self.engine = Engine() In this example, Cars are not Engines, but they have an Engine. Hence composition. Delegation provides a mechanism of code-sharing separate from inheritance, and often used instead of inheritance, or to compliment it. One object delegates to another object if the first explicitly calls the second: # self is a Car instance. self.engine.start() Delegation and composition often go together, but they don't necessarily have to. One can delegate to an object "outside" of the class, although that technique is not often used in Python. But broadly speaking, if your instance uses: super().method() that's an inheritance call. (It is only needed when you overload method.) If you write something like: SomeClass.method(self) that's delegation. Objects can delegate to anything they like, but if they delegate to a superclass, we might call it inheritance even though it lacks the property of being automatically handled by the interpreter. So one might loosely say that inheritance is a special case of delegation. Note that in languages without any form of super() or "next_class" or whatever you call it, that sort of manual delegation may be the only way to overload an inherited method. > Is inheritance only a thing > if it happens on the line of code that says "class X"? (Not the case > in Pike.) I don't think the syntax is important. You could say: @inherits_from(Parrot) class Norwegian_Blue: pass if you prefer. Defining the decorator is left as an exercise. I can't comment on Pike, since you haven't described how it behaves. As I said, in some languages mixins define inheritance without subclassing; in Python virtual subclasses define subclassing without inheritance. > Is inheritance only a thing if it happens as the class is > first created? (Is the case with mixins.) I don't understand what you mean here. Do you mean that mixins inject their methods into the class at creation time, and then no longer are referenced? That's not what happens in Python. Mixins use the same method resolution mechanism as other superclasses, which means it happens on demand, not at creation time. >>> class Mixin: ... def method(self): ... print("Creation time") ... >>> class Spam(Mixin): ... pass ... >>> Mixin.method = lambda self: print("Call time") >>> Spam().method() Call time -- Steve ___ Python-ideas mailing list -- python-ideas@python.org To unsu
[Python-ideas] Conditions for a coherent MI relationship [was Re: Re: mro and super don't feel so pythonic]
On Sat, Apr 16, 2022 at 11:07:00AM +1000, Chris Angelico wrote: > On Sat, 16 Apr 2022 at 11:00, Steven D'Aprano wrote: > > > and therefore > > > would become the only thing that offers "full MI", displacing other > > > languages. It's a meaningless concept, unless there is some form of > > > absolute completeness that can be attained > > > > Well duh Chris, sometimes I wonder if you read my posts before jumping > > in to disagree with me, that is *exactly* what I am arguing. > > You placed a LOT of caveats on it. I don't count that as "absolute > completeness". It is the most complete that YOU, right now, think > could ever be possible. Which conditions would you drop? There's not that many, really. Five. Six if you include the "no cycles" requirement for the DAG, which I think is so obviously necessary that it is barely worth mentioning. The most subjective is the requirement for automatic conflict resolution. It is a legitimate design choice to give up automatic conflict resolution (that's what C++ and Eiffel do) but that would be a breaking change for Python. So come on Chris, back up your disagreement with something objective, not just wishy-washy "anything might happen in the future!" nonsense. No, not everything is possible. We're never going to discover a new odd number between 3 and 5, or that 7 isn't really prime, or that cats are actually a type of plant, or that Australia doesn't exist. So be concrete: which of my preconditions do you want to challenge? - The inheritance model automatically resolves conflicts. As I said, it is a legitimate design choice to give that up, but it would be a breaking change for Python so we can rule it out. In any case, languages without automatic conflict resolution do less than languages with them. (That might be a good thing.) - The MRO is entirely dependendent on the shape of the inheritance graph, and not on incidental properties like the name of classes. Let's hear your justification for why breaking that condition is good. "I changed my class name from Spam to Eggs, and suddenly the inheritance relationships between my classes changed." "That's not a bug, that's a feature!!!" - the inheritance model is consistent, monotonic and preserves local precedence order (C3 linearization). Which of those three will you give up, and why is that a good thing? "In my class Spam, superclass A takes precedence over B, but when I subclass Spam, the precedence swaps and B comes before A." "That's not a bug, that's a feature!!!" > > If you exclude models of MI which are logically incoherent and > > inconsistent, (such as Python's prior to version 2.3), then Python's > > model of MI is objectively as complete as you can get. > > If you assume that what we know in 2022 is the most we will ever know, > then yes, you would be correct. Do you really think that nobody will > ever learn anything new about ways of doing MI? Yes. Its a DAG of superclass/subclass relationships. There is only one way to draw that graph that is coherent. This is like sorting. Of course people can develop new and faster sort algorithms which use less memory, but nobody is going to discover that all the old sort algorithms are wrong and 5 should come before 2. We might discover better algorithms for linearizing the superclasses, we might even discover a bug in the C3 algorithm. But we aren't going to discover that having your inheritance relationships flip order when you subclass is good, or that the order of linearization should depend on the time of day, or that violating local precedence is a good thing. > I don't know whether you're mistaken or utterly arrogant. Do you think they are the only two choices? Are you such a contrarian that you refuse to even consider that I might be right? I have never claimed to be omniscient. Of course I could be wrong. I may have been mislead, or misunderstood the state of the art. If you have something more than just wishful thinking about what "might" be discovered in the future, please tell me. I welcome corrections which are objective and based on proven facts. -- 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/HX6TBTXKKFQAVZM6AJ6S6BDPB5R7PUM4/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Fri, Apr 15, 2022 at 05:41:55PM -, malmiteria wrote: > Sticking to the way its done "just" because it's the way it's done > helps stabilising the language, but it makes it possible to miss > improvements. > > Overall, if there's only valid reasons to implement a change, this > change doesn't break anything and there's no valid reason not to > implement it, You can't change existing behaviour without breaking things. > and this change is not "full MI", fine, we're out of > full MI, what's the big deal? The big deal is that right now there are programs which rely on Python providing MI in full generality, including class hierarchies with method conflicts. Whether they should is another question, but they do, and the interpreter resolves those conflicts for them. If you put in restrictions to MI that raises an error on method conflicts, that will break their code, and as a matter of policy that will not happen. Just because the language definition of MI is fully general doesn't mean that frameworks have to use that full generality. Zope and Plone have moved away from using MI to more composition in order to escape some of the problems they were facing. There is nothing wrong with frameworks or libraries introducing their own conventions, enforced by metaclasses or decorators or whatever you want, to implement C++ or Eiffel style restrictions on method conflicts. > Someone mentionned the "class A(B(C)):" syntax was already meaning > something, i've tried a few things, but overall, most scenarios simply > fail with this syntax today. The only one i could make work was "class > A(namedtuple(...not a class...)):" Right. The *syntax* B(C) means to call object B with argument C, and that applies inside class definitions too. You can't change the meaning of that syntax. It will always mean call object B with argument C. Are you aware that class definition syntax accepts arbitrary keyword arguments and passes them on to the `__init_subclass__` method? >>> class A(int, spam=1, eggs=2): ... pass ... Traceback (most recent call last): File "", line 1, in TypeError: A.__init_subclass__() takes no keyword arguments Right now, the only one which has meaning to the interpreter is `metaclass=expression`. > If anyone has any source / talks on that, i would love to read it. Did you read the links to Michele Simionato's posts on Artima I posted? If not, then why should anyone bother sending you more links that you won't read? -- 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/2DJ3HRXBXFQ3QK25TQLO2IPNUIKDCTMM/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Sat, 16 Apr 2022 at 11:00, Steven D'Aprano wrote: > > and therefore > > would become the only thing that offers "full MI", displacing other > > languages. It's a meaningless concept, unless there is some form of > > absolute completeness that can be attained > > Well duh Chris, sometimes I wonder if you read my posts before jumping > in to disagree with me, that is *exactly* what I am arguing. You placed a LOT of caveats on it. I don't count that as "absolute completeness". It is the most complete that YOU, right now, think could ever be possible. > If you exclude models of MI which are logically incoherent and > inconsistent, (such as Python's prior to version 2.3), then Python's > model of MI is objectively as complete as you can get. If you assume that what we know in 2022 is the most we will ever know, then yes, you would be correct. Do you really think that nobody will ever learn anything new about ways of doing MI? I don't know whether you're mistaken or utterly arrogant. > > My view: If a class inherits two parents, in any meaning of the word > > "inherits" that follows the normal expectation that a subclass IS an > > instance of its parent class(es), then it's MI. > > Inheritance and "is-a" relationships are independent. > > In some languages (but not Python), mixins provide inheritance but not > an "is-a" relationship. In Python, virtual subclassing provides "is-a" > without inheritance. Virtual subclassing is still subclassing, just implemented differently. Reassigning to __class__ is still subclassing, just spelled differently. What is "inheritance" if it isn't that is-a relationship? How do you distinguish inheritance from delegation? Is inheritance only a thing if it happens on the line of code that says "class X"? (Not the case in Pike.) Is inheritance only a thing if it happens as the class is first created? (Is the case with mixins.) What's your point? ChrisA ___ 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/EVTHYR56KAKVUF7ZLPVREVHD2M2PI6EL/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Sat, 16 Apr 2022 at 11:07, Chris Angelico wrote: > > On Sat, 16 Apr 2022 at 11:00, Steven D'Aprano wrote: > > > and therefore > > > would become the only thing that offers "full MI", displacing other > > > languages. It's a meaningless concept, unless there is some form of > > > absolute completeness that can be attained > > > > Well duh Chris, sometimes I wonder if you read my posts before jumping > > in to disagree with me, that is *exactly* what I am arguing. > > You placed a LOT of caveats on it. I don't count that as "absolute > completeness". It is the most complete that YOU, right now, think > could ever be possible. For a slightly tangential comparison: If you assume that "numbers" are only those on the real number line, then you assume that returning an error when asking for the square root of a negative number is the ONLY way to do things, and a mathematical library that can handle all real numbers is absolutely complete. But based on your knowledge of Python's numeric tower, I think you'd agree that this view, despite having been firmly held for centuries, isn't actually complete. ChrisA ___ 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/WEXGRVKZ7EOLM2D7EZZVS3EED7GBGGW2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Fri, Apr 15, 2022 at 11:12:26PM +1000, Chris Angelico wrote: > > If you look at languages that implement MI, and pick the implementations > > which allow it with the fewest restrictions, then that is "full MI". > > I'm with Greg on this one, for the simple reason that a future > language could have fewer restrictions than Python does, Not without making inheritance incoherent and inconsistent. E.g. in Python 2.2 and below, it was possible to design class hierarchies that resulted in methods being called twice or more times. Other signs of an incoherent MI model might include: * loops or cycles in your precedence graph; * superclasses being skipped; * inconsistent ordering (class A coming before class B for one method, but B before A for another method); * violating local precedence order, e.g. class Spam has A come before B, but in Spam's subclass the order flips to B before A; * or the order changes if you change the name of a class and nothing else about it. These are all Bad Thingsā¢ and Python avoids them all. You can only generalise MI up to a certain point, after which it becomes inconsistent and therefore buggy. That's why Python 2.2's MRO was dropped for the C3 linearization in 2.3: it was buggy. I'm assuming automatic conflict resolution. If its not automatic, it's not what I'm calling inheritance. If you have to manually specify which superclass to call, that's delegation. That's okay: inheritance is not the be all and end all of OOP. You can use delegation to solve problems too, or manual conflict resolution by renaming methods, as Eiffel does. And as I said before, it might be that the Eiffel or C++ model is *better* than Python's model. But given the assumptions that: - the inheritance model automatically resolves conflicts; - the MRO is entirely dependendent on the shape of the inheritance graph, and not on incidental properties like the name of classes; - the inheritance model is consistent, monotonic and preserves local precedence order (C3 linearization); then I believe that the Dylan/Python/Ruby/Perl/Raku MI model is as general as you can get, and models like Eiffel or C++ are more restrictive. I believe that you cannot drop any of those restrictions without the very idea of inheritance becoming incoherent. It is not a "No True Scotsman" fallacy. Other models of MI are legitimate even if they are not fully general. I have suggested that Python's fully generalised MI model may ultimately be worse than more restrictive models that provide less freedom to write unmaintainable code. I have repeatedly linked to the writing of Michele Simionato who explores these issues in excruciating detail. > and therefore > would become the only thing that offers "full MI", displacing other > languages. It's a meaningless concept, unless there is some form of > absolute completeness that can be attained Well duh Chris, sometimes I wonder if you read my posts before jumping in to disagree with me, that is *exactly* what I am arguing. If you exclude models of MI which are logically incoherent and inconsistent, (such as Python's prior to version 2.3), then Python's model of MI is objectively as complete as you can get. Whether I am right or wrong, this is an objective matter of fact, not a matter of taste or opinion, and it is certainly not a "No True Scotsman" value judgement against using more restrictive forms of MI. > My view: If a class inherits two parents, in any meaning of the word > "inherits" that follows the normal expectation that a subclass IS an > instance of its parent class(es), then it's MI. Inheritance and "is-a" relationships are independent. In some languages (but not Python), mixins provide inheritance but not an "is-a" relationship. In Python, virtual subclassing provides "is-a" without inheritance. -- 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/TEXBXLQ5HZFYDXO25YOGMQ7YHLS4JSQV/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Fri, Apr 15, 2022 at 2:44 PM malmiteria wrote: > I got an idea that *should* allow for some (keyword : some) of the changes > i want without any breaks, i kinda wanna take the time to think about it, and > once i'm a bit more sure of it, i'll talk about it in details. Since you are thinking of ways that won't break current code, you might as well think of ways that won't need any syntax modification/adding extra features to the language. The current capabilities we get, including being able to customize the metaclass __getattribute__ method, might allow for that - and you'd have the advantage that your ideas could be immediately be made available in a pypi package. > > ___ 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/KAJEBWZRL2OMQ3GDRQG6XNENUXS7LLWU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
Chris Angelico writes: > I'm with Greg on this one, for the simple reason that a future > language could have fewer restrictions than Python does, and therefore > would become the only thing that offers "full MI", displacing other > languages. It's a meaningless concept, unless there is some form of > absolute completeness that can be attained (and if you go for that, NO > language offers "full MI"). > > My view: If a class inherits two parents, in any meaning of the word > "inherits" that follows the normal expectation that a subclass IS an > instance of its parent class(es), then it's MI. > > So if you have "class Foo(Spam, Ham):" and it is reasonable to treat a > Foo instance as if it were a Spam instance *and* reasonable to treat a > Foo instance as if it were a Ham instance, then it's MI. > > Erroring out when there is a conflict is a restriction, but I would > avoid the term "full MI" because it's more emotive than useful. I agree with you 100%. I think i would add that what should matter is that we can describe our experiences with accurate concepts, and not that we conduct ourselves based on the concepts we know. At least when talking about potential improvments. Sticking to the way its done "just" because it's the way it's done helps stabilising the language, but it makes it possible to miss improvements. Overall, if there's only valid reasons to implement a change, this change doesn't break anything and there's no valid reason not to implement it, and this change is not "full MI", fine, we're out of full MI, what's the big deal? (I'm not saying i'm talking about my proposal here...) I got an idea that *should* allow for some (keyword : some) of the changes i want without any breaks, i kinda wanna take the time to think about it, and once i'm a bit more sure of it, i'll talk about it in details. Someone mentionned the "class A(B(C)):" syntax was already meaning something, i've tried a few things, but overall, most scenarios simply fail with this syntax today. The only one i could make work was "class A(namedtuple(...not a class...)):" If anyone has any source / talks on that, i would love to read it. And if you have ever seen this kind of syntax used, let me know. Someone mentionned they had a hard time tracking my exact proposal, i'll give an up to date proposal at some point too, i'll try to keep it short this time. I also still need to do that survey to measure what peoples intuition are. ___ 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/LE5TNQDHVW5FXKRGXPCTQTKYIHSMRDHD/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
Greg Ewing writes: > > malmiteria xD not malmalitia > Sorry! Should have gone to Specsavers... No worries :) ___ 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/PKPRE2OADUN7PUVYGYCQV27MIDWENXXP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Fri, 15 Apr 2022 at 20:40, Steven D'Aprano wrote: > > On Thu, Apr 14, 2022 at 10:46:46AM +1200, Greg Ewing wrote: > > On 13/04/22 8:29 am, Steven D'Aprano wrote: > > >>When multiple parent provide candidate to a method resolution, raise an > > >>error. > > > > > >Then you aren't doing full MI any more, > > > > That sounds like a "true Scotsman" argument. Who defines what > > "full MI" means? > > If you look at languages that implement MI, and pick the implementations > which allow it with the fewest restrictions, then that is "full MI". > I'm with Greg on this one, for the simple reason that a future language could have fewer restrictions than Python does, and therefore would become the only thing that offers "full MI", displacing other languages. It's a meaningless concept, unless there is some form of absolute completeness that can be attained (and if you go for that, NO language offers "full MI"). My view: If a class inherits two parents, in any meaning of the word "inherits" that follows the normal expectation that a subclass IS an instance of its parent class(es), then it's MI. So if you have "class Foo(Spam, Ham):" and it is reasonable to treat a Foo instance as if it were a Spam instance *and* reasonable to treat a Foo instance as if it were a Ham instance, then it's MI. Erroring out when there is a conflict is a restriction, but I would avoid the term "full MI" because it's more emotive than useful. ChrisA ___ 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/HRBMHDQSAAAWWXNBGMVXKIB34QHKYFBO/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On Thu, Apr 14, 2022 at 10:46:46AM +1200, Greg Ewing wrote: > On 13/04/22 8:29 am, Steven D'Aprano wrote: > >>When multiple parent provide candidate to a method resolution, raise an > >>error. > > > >Then you aren't doing full MI any more, > > That sounds like a "true Scotsman" argument. Who defines what > "full MI" means? If you look at languages that implement MI, and pick the implementations which allow it with the fewest restrictions, then that is "full MI". Class parent/child relationships are not the same as biological relationships: https://www.youtube.com/watch?v=fWQ7TFFKEz8 so I hope that we can agree that excluding cycles and loops in your inheritance hierarchy is a necessary restriction, for our sanity if no other reason. I don't know of any languages that allow cycles in inheritance graphs. Beyond that, I believe that Python (and other languages) allow MI with the smallest set of restrictions, namely that there is a C3 linearization possible: https://en.wikipedia.org/wiki/C3_linearization I believe that those 3 requirements in C3 are the fewest restrictions while still having logically consistent behaviour. That's what I mean by "full MI". Of course languages can impose additional restrictions, e.g. that methods are independent, there there are no diamonds, etc. But they offer less than the full generality that Python (and other languages) offer. For instance, I believe that Eiffel allows MI with diamonds, so long as methods in different branches are independent. If two classes provide the same method, Eiffel raises an exception. (Michele Simionato calls this behaviour equivalent to traits.) That is *more restrictive* than Python, and so it offers *less* than a fully general model of MI. On the other hand, sometimes "less is more", and Michele has come to believe that Python's fully general MI is too powerful to be usable, and that more restrictive versions (traits) are better, or even avoiding inheritance in favour of generics, composition and delegation. We can implement mixins, or traits, or Eiffel-style inheritance, or whatever extra restrictions you want, using decorators or metaclasses. They don't need a change to the language definition of MI. > I can think of at least two languages that do something very > similar to what malmalitia is proposing: C++ and (if I remember > rightly) Eiffel. I don't think I've heard anyone claim that > C++ doesn't do "full MI". Oooh, ooh, let me sir! "C++ doesn't do full multiple inheritance." If you have to manually call a specific method, as shown here: https://devblogs.microsoft.com/oldnewthing/20210813-05/?p=105554 you're no longer using inheritance, you're doing delegation. I make no comment on whether C++ is justified on restricting inheritance in that way. Michele Simionato declares that C++ implements MI "badly", but I don't know his reason for that judgement. Multiple inheritance is complex. Managing that complexity is hard. It may be that that best way to manage it is to forgo the full generality of MI and all the complexity it brings, or by not using inheritance at all. But either way, Python currently offers MI in its full generality. Restricting it at the language level is a breaking change, and will not happen. -- 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/W3JF6YI45XROPERQOFZ24TMEZIOUNLAW/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: mro and super don't feel so pythonic
On 15/04/22 4:45 am, malmiteria wrote: malmiteria xD not malmalitia Sorry! Should have gone to Specsavers... -- Greg ___ 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/MWDXAJDS37HPCKKWX7FSCPJFS72SKPFM/ Code of Conduct: http://python.org/psf/codeofconduct/