[Python-ideas] Keyword for direct pass through of kwargs to super

Chris Angelico rosuav at gmail.com
Sat May 26 04:12:49 EDT 2018


On Sat, May 26, 2018 at 5:39 PM, Michael Lohmann <mial.lohmann at gmail.com> wrote:
> [Steven D'Aprano]
>>    obj = Aardvark(27, spam=3, eggs=5, cheese=True)
>>
>> So you look up help(Aardvark), and it tells you that the signature is
>>
>>    Aardvark.__init__(self, foo)
>>
>> What the hell? If Aardvark.__init__ only takes a single argument
> This is wrong! This would at some point down the line throw an error
>    TypeError: __init__() got an unexpected keyword argument 'eggs‘
> (or at some point **kwargs are being accepted and not passed on to super which would be terrible on its own).
>
> The whole point I was trying to make is: If it doesn’t make any sense to init a class with **kwargs: why write down that it would (or even **could**) accept them? Shouldn’t the init tell you something like 'If you instantiate this class then this is everything you can give me'? Well, right now in addition it says 'Just give me anything with keywords‘. I would think that something like 'Oh, and if I am in the middle of an MRO: I will pass everything down the line‘ would be a much better description of it’s true intentions instead.
>
>
> [Carl Smith]
>> By using **kargs in the constructor and the call
>> to `super`, you are indicating that the signature passes through
> But can you be certain? Couldn’t someone have just used a `kargs.pop('eggs')`? Okay. You could argue that they probably wouldn’t have done so. But for making automated documentation it probably would be useful to make sure it didn’t happen.
>
> I think that (as Raymond Hettinger once said) 'super is super', but can’t you make it a bit smarter with telling it: 'Hey - If you don’t expect 'eggs', keep calm, it probably (or rather certainly) wasn’t meant for you so just pass it on to your super'.
>

Let's get some somewhat-more-plausible examples.

class Pizza:
    def __init__(self, *, size, price):
        print("The price of this %s pizza is:", (size, price))

class HawaiianPizza(Pizza):
    def __init__(self, *, pineapple="chunked", **kw):
        print("This pizza has %s pineapple." % pineapple)
        super().__init__(**kw)

class CheesyCrust(Pizza):
    """Mixin to alter the pizza's crust"""
    def __init__(self, *, crust_cheese="cheddar", surcharge=1.50):
        print("Surcharge %.2f for %s crust" % (surcharge, crust_cheese))
        super().__init__(price=kw.pop("price") + surcharge, **kw)

class BestPizza(HawaiianPizza, CheesyCrust):
    """Actually, the best pizza is pepperoni. Debate away!"""

menu = [
    BestPizza(size="large", price=12.50),
    BestPizza(size="personal", price=8.50),
]

Okay. Now what are the possible keyword args for a BestPizza? The
*entire set* of args for the hierarchy. You can set size, price,
pineapple, crust_cheese, and surcharge. The fact that some of them (or
even ALL of them, at the leaf node) are simply passed on up the chain
doesn't change the fact that they're all valid.

Does that make sense?

ChrisA


More information about the Python-ideas mailing list