2018-05-28 9:44 GMT+02:00 Michael Lohmann <mial.lohm...@gmail.com>:
>
>> I'd say NOT wanting to call an __init__ method of a superclass is a
>> rather uncommon occurence. It's generally a huge error. So I think
>> it's worth not accomodating that.
>
> I will give you an example then where I am absolutely fine with calling 
> super().__init__ in all classes and describe why I am not really satisfied 
> with the current status. (It is from my email from yesterday 17:19 GMT):
>
>> What bugs me is that in my example from yesterday (
>>     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)
>> ) if you want to instantiate an Aardvark directly there is NO WAY EVER that 
>> you could give him ANY kwargs. So why should the __init__ indicate something 
>> else? Well, just to make the MRO work. All I want is to make it as obvious 
>> as possible that an Aardvark only takes `quantity` as input, but is fully 
>> "cooperative" with other classes if it is in the middle of the MRO (by which 
>> I mean that it will automatically call the __init__ and hand on any kwargs 
>> it didn’t expect to a class from a different branch of the class hierarchy).

This is more an issue with your Ethel class. In *normal* subclassing,
it's init would look like:

class Ethel(Aardvark, Clever):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

and you'd instantiate it like:
e = Ethel(quantity="some spam", cleverness=1000)
or even (because keyword argument order doesn't matter):
e = Ethel(cleverness=1000, quantity="some spam")

Because don't forget:
assert isinstance(e, Ethel)
assert isinstance(e, Aardvark)
assert isinstance(e, Clever)

will all pass perfectly fine. It's not just an Ethel or an Aardvark,
it's also a Clever. (which doesn't sound like it makes sense...perhaps
clever should be an attribute on an Aardvark/Ethel instead ?).

That all aside, for a moment. You actually CAN call
object.__init__(**kwargs) no problem - as long as kwargs is empty. I'd
have written your classes like this:

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, **kwargs):
        print("You are %d clever" % cleverness)
        super().__init__(**kwargs)

class Ethel(Aardvark, Clever):
    """Ethel is a very clever Aardvark"""
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

Just try it - it works perfectly fine. Each constructor will consume
the keywords meant for it, therefore, the last super() call will call
the object constructor without keyword arguments.

**kwargs is the price we have to pay for good multiple inheritance -
and IMO, it's a low one.

If we're talking about signalling what the arguments mean, just ensure
you have a good docstring.

class Aardvark:
    def __init__(self, quantity, **kwargs):
        """
        Aardvarks are gentle creatures, and therefore cooperate with
multiple inheritance.
        :param quantity: The quantity of Aardvark(s).
        """
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to