I'm using Python 3.6. This code, used as a decorator to a python function, will cause the function to return a dict of POSITION_OR_KEYWORD
arguments.
I used this to create a standard interface to a factory function.
Inspired by this Stack Overflow post, and implemented using a dictionary-flattening function from this previous post.
Eg.
def example(one=1, two=2):
return {'one':one, 'two':two}
is equivalent to:
@return_kwargs
def example(one=1, two=2):
pass
import inspect
from functools import wraps
from itertools import chain, starmap
def flatten_dict(dictionary):
"""Flatten a nested dictionary structure"""
def unpack(parent_key, parent_value):
"""Unpack one level of nesting in a dictionary"""
try:
items = parent_value.items()
except AttributeError:
# parent_value was not a dict, no need to flatten
yield (parent_key, parent_value)
else:
for key, value in items:
yield (key, value)
# Put each key into a tuple to initiate building a tuple of subkeys
dictionary = {key: value for key, value in dictionary.items()}
# Keep unpacking the dictionary until all value's are not dictionary's
dictionary = dict(chain.from_iterable(starmap(unpack, dictionary.items())))
return dictionary
def return_kwargs(func):
"""Cause the wrapped function to return a dict of keyword arguments"""
@wraps(func)
def wrap(*args, **kwargs):
bound_arguments = inspect.signature(func).bind(*args, **kwargs)
bound_arguments.apply_defaults()
return flatten_dict(dict(bound_arguments.arguments))
return wrap
Let me know how you would implement the idea, whats ugly, corner cases I have missed.
@return_kwargs def example(one=1, two=2, **kwargs): pass example(**example()) Out[9]: {'kwargs': {'kwargs': {}}, 'one': 1, 'two': 2}
\$\endgroup\$