Skip to content

Instantly share code, notes, and snippets.

@jsbueno
Created May 6, 2020 14:49
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsbueno/f689a181d50384f627b43b9b2aabe4f2 to your computer and use it in GitHub Desktop.
Save jsbueno/f689a181d50384f627b43b9b2aabe4f2 to your computer and use it in GitHub Desktop.
Auto assign decorator - eliminates attribute assignment boilerplate in __init__ functions
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
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment