> If I understand correctly, the essence of your argument seems to be
> that you want be able to write a class A, and you want to be able to use that
> class EITHER as the top of an inheritance chain (i.e., have it inherit
> directly from object) OR in the middle of an inheritance chain (i.e.,
> inheriting from some other class, but not object).
Well, it does not necessarily inherit from object, but from any class, that
does not accept any more kwargs. E.g. if you have a diamond structure as your
class-hierachy then one branch could forward information to the second (if you
understand what I mean?).
> But I don't really see how your solution of magically making kwargs appear
> and disappear is a good solution to that problem.
I intended the following text for the python-list mailing-list, but it I think
I might have structured my ideas a bit better than in my previous messages and
the summary in __Reason__ might tackle why this could be a nice idea (spoiler:
make super even more super by doing things if it is NOT there in a clever
manner).
Let us start with a simple class:
class Aardvark:
def __init__(self, quantity):
print("There is some quantity:", quantity)
Well, that works nicely and we can go and send our Aardvark to survey some
quantities. But if we now want to get the multi-inheritance to work properly we
need to change it to:
class Aardvark:
def __init__(self, quantity, **kwargs):
print("There is some quantity:", quantity)
# I actually don’t care about **kwargs and just hand them on
super().__init__(**kwargs)
class Clever:
def __init__(self, cleverness=1):
print("You are %d clever“ % cleverness)
class Ethel(Aardvark, Clever):
"""Ethel is a very clever Aardvark"""
def __init__(self):
super().__init__(quantity="some spam", cleverness=1000)
But if you now look at the declaration of the Aardvark .__init__, it seems like
you could instantiate it with **kwargs. This in fact is not true. As soon as
you create a direct instance of Aardvark, `object` as the super() doesn’t
accept any kwargs. So basically I think that the parameters for the init should
just say `quantity ` while still preserving the functionality.
Now that obviously doesn’t work until now. But could you add something that
lets this class tell the interpreter instead: "Hey, could you just forward
anything that this init doesn’t need to super().__init__" ? I have something
like this in mind:
class Aardvark:
@bypass_kwargs_to_super
def __init__(self, *, quantity):
print("There is some quantity:", quantity)
super().__init__()
This would collect everything "behind the scenes" that usually **kwargs would
have collected and "append" it to the super call. Question: If Aardvark knows
that he really does not need the kwargs himself: why give them to him in the
first place? I mean, I trust him - he seems like a very nice guy, but he might
have accidentally forgotten to forward them unintentionally.
You would obviously still be able to use **kwargs the usual way but then you
couldn’t use this technique and would need to take care of passing down all the
information to super() yourself as usual.
__Reason__: With something like this it is immediately obvious that Aardvark
ONLY takes `quantity` as an input if you instantiate it directly but if
subclassed it is able to hand information down the MRO to something from a
different "Branch". And in addition to the better human readability: any form
of automated docstring-genaration now can be certain that you don’t do anything
with (or to) the **kwargs (since the init doesn’t get them in the first place).
In addition it could make super even more super by doing something if it is NOT
there as proposed in the second of the the following problems.
Of course you need to be quite clever to do this properly, for example
1) What to do if there are collisions between the bypassed kwargs and the ones
from the init call? - Probably keep the ones you bypassed since they come from
the top of the MRO
2) What do you do if super().__init__ was not called? The most clever thing
would be to go „up and to the next branch“ of the inheritance diagram. As in:
if Aardvark is a Subclass of Animal, don’t call its init but directly Clevers -
(you would have to look up the MRO of the super of Aardvark and skip them in
the Ethel MRO before calling the next init automatically).
In theory you could also add something that forwards *args as well but the
usage of that is probably much more limited...
On thing that might look a bit strange is that you actually could actually pass
in additional kwargs despite the init saying otherwise:
`Aardvark(quantity='some spam', something="Object will throw an error now
unexpected kwarg")`
and this would then throw an error that "object (instead of Aardvark) does not
expect something". But I guess that would be okay since the init now is much
better readable of what it actually expects.
Michael
_______________________________________________
Python-ideas mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/