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

2018-05-28 11:07 GMT+02:00 Michael Lohmann <mial.lohmann@gmail.com>:
But maybe it is just me who thinks that you should make it as obvious as possible what a class itself really can get as an input and what is done just to get the multiple inheritance to work... So I think if no one else agrees with me, we don’t need to further spam everybody.
I think the largest difference is that most people have a different opinion about what is more explicit/obvious. It does look like you could build something like this for yourself with a decorator: from inspect import signature, Parameter def forwards_kwargs_to_super(classname): def deco(method): sig = signature(method) numargs = len([param for param in sig.parameters.values() if param.kind is Parameter.POSITIONAL_ONLY]) keykwargs = {param.name for param in sig.parameters.values() if param.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY)} def newinit(self, *args, **kwargs): print(f"Call looks like: {classname}: {args[:numargs]}, { {key: val for key, val in kwargs.items() if key in keykwargs} }") method(self, *args[:numargs], **{key: val for key, val in kwargs.items() if key in keykwargs}) super(globals()[classname], self).__init__(*args[numargs:], **{key: val for key, val in kwargs.items() if key not in keykwargs}) return newinit return deco And then use it like this: class Aardvark: @forwards_kwargs_to_super("Aardvark") def __init__(self, quantity): print("There is some quantity:", quantity) # I actually don’t care about **kwargs and just hand them on class Clever: @forwards_kwargs_to_super("Clever") def __init__(self, cleverness=1): print("You are %d clever" % cleverness) class Ethel(Aardvark, Clever): """Ethel is a very clever Aardvark""" @forwards_kwargs_to_super("Ethel") def __init__(self): pass e = Ethel(quantity="some spam", cleverness=100) Disclaimer: - Whenever you import the inspect module, you should ask yourself whether it's really a good idea. - I'm assuming that decorated functions have no *args or **kwargs in their signature that you DO want to accept, and that all arguments with a default value are given as keyword arguments. - If you are passing new positional arguments with this function, the subclass positional arguments need to come before the superclass positional arguments (only important if both have positional arguments.) - If you use multiple decorators, this should be the innermost decorator, or it'll probably make your code barf at runtime. - If you try do this in my company, i'll do whatever I can to get you fired. For the love of Python, don't use this code at places where anybody except you has to do maintenance. And if you come back in half a year and are amazed by your own code, I promise you'll understand why this might not be a real good solution. - Yes, passing your class name and then getting it from globals is an ugly hack. The alternative is grabbing it from the stack. If anybody else has a better idea, feel free, but AFAIK it's impossible to do this better. (I once wrote an overload decorator as a personal exercise, using the stack hack.) - I haven't tested this with actual positional arguments, but I -think- it will work.

Bright idea the moment after sending that mail: You could remove the globals() hack if you make it a class decorator instead.

Bright idea the moment after sending that mail: You could remove the globals() hack if you make it a class decorator instead.
participants (1)
-
Jacco van Dorp