Joao S. O. Bueno wrote:
Here - with the current inspect.Signature, it is straightforward to get a decorator that can do that covering most, if not all, corner cases, and even adding some extra functionality: https://gist.github.com/jsbueno/f689a181d50384f627b43b9b2aabe4f2
from inspect import signature, Parameter from functools import wraps, partial
def autoassign(func=None, *, expand_kwargs=False):
if not func: return partial(autoassign, expand_kwargs=expand_kwargs) sig = signature(func) @wraps(func) def wrapper(*args, **kwargs): instance = args[0] bound_args = sig.bind(*args, **kwargs) bound_args.apply_defaults() for i, (key, value) in enumerate(bound_args.arguments.items()): if i == 0 or sig.parameters[key].kind == Parameter.POSITIONAL_ONLY: continue if expand_kwargs and sig.parameters[key].kind == Parameter.VAR_KEYWORD: for kwkey, kwvalue in value.items(): setattr(instance, kwkey, kwvalue) continue setattr(instance, key, value) return func(*args, **kwargs) return wrapper
""" class A: @autoassign def __init__(self, a, b, c=3): pass
a = A(1, 2) assert a.a == 1 and a.b == 2 and a.c == 3 """
Is there a good reason to exclude positional only args from this? I imagine if you are passing them to init you still want them to be treated internally in the same way as the other args.
Could we put this into the standard library, so that IDEs and linters are programmed to recognise it?
I agree, without this being recognised by linters/IDEs any attrs will show with ugly warnings which would stop anyone from using it.