Steven D'Aprano wrote: > Proposal: > We should have a mechanism that collects the current function or > method's parameters into a dict, similar to the way locals() returns all > local variables. > This mechanism could be a new function,or it could even be a magic local > variable inside each function, similar to what is done to make super() > work. But for the sake of this discussion, I'll assume it is a function, > parameters(), without worrying about whether it is a built-in or > imported from the inspect module. > So given a function signature: > def func(spam, eggs, cheese=None): > > and a call to it func(1, 2), then inside the body of the function, > calling parameters() will return the dict: > {'spam': 1, 'eggs': 2, 'cheese': None} > [...] > Another pattern would be to pass on your parameters to the superclasses: > super().method(**parameters())
I took a stab at this. This should work regardless of where the function is defined. ``` import inspect def parameters(*, expand_kwargs=True): frame = inspect.currentframe().f_back code = frame.f_code varnames = code.co_varnames end = code.co_argcount + code.co_kwonlyargcount result = { name: frame.f_locals[name] for name in varnames[:end] } # **kwargs if code.co_flags & inspect.CO_VARKEYWORDS: index = end if code.co_flags & inspect.CO_VARARGS: index += 1 name = varnames[index] var = frame.f_locals[name] if expand_kwargs: result.update(var) else: result[var] = name return result def foo1(a, b=1, *args, c, **d): x = 1 y = 2 print(parameters()) print(a, b, c, d) foo2(**parameters()) def foo2(a, b=1, *args, c, **d): print(a, b, c, d) foo1(1, 2, 3, 4, c=5, e=6, f=7) ``` Output: ``` {'a': 1, 'b': 2, 'c': 5, 'e': 6, 'f': 7} 1 2 5 {'e': 6, 'f': 7} 1 2 5 {'e': 6, 'f': 7} ``` Note that `parameters()` intentionally doesn't contain `'args': (3, 4)` because then `foo2(**parameters())` would see `args` as a keyword argument within `d` instead of bound to the parameter `*args`. So naturally I tried `foo2(*args, **parameters())` but that gave me `TypeError: foo2() got multiple values for argument 'a'`. So if you want to pass all arguments from one function to another, you need more than a dict if the inner signature include `*args`, and obviously even more so if it includes positional only parameters.
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/QQKU24OU67ZPPFSWJHN7OCJXR7V2Z62A/ Code of Conduct: http://python.org/psf/codeofconduct/