Eric V. Smith writes:
> I've said this before, but I'll repeat it here: if your proposal is to 
> have super().something raise an error if "something" exists on more than 
> one parent class (via the MRO), then that's a breaking change and it 
> will not be accepted.
The expliciteness required error should be raise at attribute / method access, 
not through super.
My proposal would completely detach method resolution from calls to super.
essentially:
```
class A:
    val = 1
class B:
    val = 2
class C(A,B): pass

C.val # raises an explicitness required error
```

It's fair to assume super would need to know what parent class it should target 
however, especially since part of my proposal is to make it so that super can 
take as an argument the class it targets, instead of the previous in MRO order, 
but that is not something i consider an "active" part of my proposal (the idea 
that  super needs to be passed a parent as argument in case of MI).
As i was answering Ronald Oussoren, i figured that in case of MI, a call to 
super with no argument could simply loop over call to super with each parent, 
one after the other.
That would keep it a nice way to tell "go fetch all parents behaviors" without 
having to write down one line per parent.

I think it would behave 'strictly' as today's super calls, except in cases 
where one class appears multiple time in the inheritance tree (and is visited 
through calls to super).
For those scenarios, i have a dedicated answer.

Your exemple actually is one of those cases, since calls to super do visit the 
object parent class.

Let's start with super() implicitelly calling super on all parents one after 
the other.

```
class A:
     def foo(self):
         print("A")
         try:
             super().foo()
         except AttributeError:
             print('no parent defines foo')

class B:
     def foo(self):
         print("B")
         try:
             super().foo()
         except AttributeError:
             print('no parent defines foo')

class C(A, B):
     def foo(self):
         print("C")
         super().foo()

C().foo()
```


This would output (not accounting for the parent appearing multiple time 
proposal) :
```
C
A
no parent defines foo
B
no parent defines foo
```

in this case, C would be equivalent to, (but not require any rewrites):
```
class C(A, B):
     def foo(self):
         print("C")
         super(A, self).foo() 
         super(B, self).foo() # keep in mind, in my proposal, the class passed 
as an argument is the one we target.
```
I occasionally write it down without the self, or with self.__as_parent__(..) 
but overall, i'm fine with super(class, self), as long as the class is the 
target, not the previous to the target in MRO order.
You get the idea.

If accounting for the parent appearing multiple time (i'll just call it the 
diamond case for now)
my proposal for those is to have a module strats, that would allow to decide 
what occurence of a reoccuring parent should be visited or not.
the default strat would be 'last', as to match the current behavior.

Idk exactly what API is the better for this proposal, but since the goal is for 
it to default to today's behavior, we wouldn't need to write down anything 
related to it in this scenario, we would get that output
```
C
A
B
no parent defines foo
```
Which is the one you want.

TLDR:
with my full proposal, the code you presented me won't break.
It won't even change behavior at all.

Or in other term, I acknowledge breaking changes are bad, but they're not 
impossible to cover for.
And i think i have covered for it fairly extensively.

If you think you can come up with code that would break under my proposal, hit 
me. I wanna have the least amount of breaking change.
And as much as possible, i wanna cover for those breaking changes, to find a 
way to update my proposal, so those aren't breaking changes anymore.

One thing i can think of rn is that calls to super in classes without parent 
would turn out to break with my proposal, since they would now refer to object 
anytime. That needs covering up too, and i'll be thinking on that one too.
Like i've done for every scenario i've been opposed with so far, i think.
_______________________________________________
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/SV4F7I2XNX3A2YCQ747TJW3XJF5CS2LF/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to