[Python-ideas] mro and super don't feel so pythonic

2022-03-26 Thread malmiteria
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

2022-03-26 Thread David Mertz, Ph.D.
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

2022-03-26 Thread Joao S. O. Bueno
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

2022-03-26 Thread malmiteria
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

2022-03-26 Thread Christopher Barker
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

2022-03-26 Thread malmiteria
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

2022-03-26 Thread malmiteria
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

2022-03-26 Thread Brendan Barnwell

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

2022-03-26 Thread Ethan Furman

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

2022-03-26 Thread Ethan Furman

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

2022-03-26 Thread Michael Green
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

2022-03-26 Thread Christopher Barker
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

2022-03-26 Thread Christopher Barker
> 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

2022-03-26 Thread Steven D'Aprano
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

2022-03-26 Thread Steven D'Aprano
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

2022-03-26 Thread Steven D'Aprano
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

2022-03-26 Thread Christopher Barker
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/