5 ms·
Maybe you could make a function decorator that looked for a special type of default value indicating how to make the default value each time. Similar to `attr.F
by Strilanc 5y ago
Maybe you could make a function decorator that looked for a special type of default value indicating how to make the default value each time. Similar to `attr.Factory` [1] for `attr.dataclass` annotations.
1: https://www.attrs.org/en/stable/api.html#attrs.Factory https://www.attrs.org/en/stable/api.html#attrs.Factory
- softwaredoug 5y agoI was thinking this too, if a decorator could make this easier. I'd also like whatever a solution is to work well with type annotations. I'm surprised there isn't a pep to improve the situation. (Maybe there is and I haven't found it!)
- hultner 5y agoThere is, see my comment here: https://news.ycombinator.com/item?id=30047413 https://news.ycombinator.com/item?id=30047413
- dragonwriter 5y ago> Maybe you could make a function decorator that looked for a special type of default value If you make the functions to supply late-bound defaults arguments to the decorator, its pretty doable; here’s what I just threw together. from inspect import signature, Parameter def with_deferred_defaults(*args, **kwargs): def decorate(fun): parameters = signature(fun).parameters positional_parameters = [parameter for parameter in parameters.values() if parameter.kind in [Parameter.POSITIONAL_ONLY, Parameter.POSITIONAL_OR_KEYWORD]] defaults = list(args) kwdefaults = kwargs def wrapper(*args, **kwargs): args = list(args) if len(args) < len(defaults): args = args + [arg() for arg in defaults[len(args):]] new_kwargs = {k: v() for k, v in kwdefaults.items()} new_kwargs.update(kwargs) for i, p in enumerate(positional_parameters): if i >= len(args): if p.name in new_kwargs: args.extend([None]*(1+i-len(args))) args[i] = new_kwargs[p.name] del new_kwargs[p.name] elif p.default is Parameter.empty: raise TypeError('Missing argument: {}'.format(p.name)) else: if p.name in new_kwargs: del new_kwargs[p.name] return fun(*args, **new_kwargs) return wrapper return decorate