I don't want to use *args or **kwargs since I can't ch开发者_运维问答ange function declaration.
For example:
def foo( a, b, c ) """Lets say values passed to a, b and c are 1,2 and 3 respectively"""
...
...
""" I would like to generate an object preferably a dictionary such as {'a':1, 'b':2, 'c':3} """
...
...
Can anyone suggest a way to do this? Thanks in advance.
If you can't change the function "declaration" (why not?) but you can change the contents of the function, then just create the dictionary as you want it:
def foo(a, b, c):
mydict = {'a': a, 'b': b, 'c': c}
If that doesn't work, I think you need a better explanation of what you want and what the constraints are in your case.
This is also going to give similar results in the above case (where you don't show any local variables other than the arguments), but be warned that you should not try to modify locals():
def foo(a, b, c):
mydict = locals()
@Rohit, we do not understand what you mean when you say "the function declaration". If you mean you don't want to change the API of the function (the documented way the function is called), perhaps because you have existing code already calling an existing function, then you can still use the **kwargs
notation, and the callers will never know:
def foo(a, b, c):
return a + b + c
def foo(**kwargs):
total = 0
for x in ("a", "b", "c"):
assert x in kwargs
total += kwargs[x]
return total
def bar():
foo(3, 5, 7)
bar()
cannot tell which version of foo()
it is calling, and does not care.
Perhaps you are looking for a "wrapper" you can wrap around existing function objects, without changing the actual source code of the function object?
def make_wrapper(fn, *arg_names):
def wrapped_fn(*args):
mydict = dict(tup for tup in zip(arg_names, args))
print("TEST: mydict: %s" % str(mydict))
return fn(*args)
return wrapped_fn
def foo(a, b, c):
return a + b + c
foo = make_wrapper(foo, "a", "b", "c")
foo(3, 5, 7)
The new wrapped function gathers the arguments into mydict
and prints mydict
before calling the function.
By diligent searching of StackOverflow, I found out how to do this. You use the inspect
module.
import inspect
def make_wrapper(fn):
arg_names = inspect.getargspec(fn)[0]
def wrapped_fn(*args, **kwargs):
# mydict now gets all expected positional arguments:
mydict = dict(tup for tup in zip(arg_names, args))
# special name "__args" gets list of all positional arguments
mydict["__args"] = args
# mydict now updated with all keyword arguments
mydict.update(kwargs)
# mydict now has full information on all arguments of any sort
print("TEST: mydict: %s" % str(mydict))
return fn(*args, **kwargs)
return wrapped_fn
def foo(a, b, c, *args, **kwargs):
# a, b, and c must be set; extra, unexpected args will go in args list
return a + b + c
foo = make_wrapper(foo)
foo(3, 5, 7, 1, 2)
# prints: TEST: mydict: {'a': 3, 'c': 7, 'b': 5, '__args': (3, 5, 7, 1, 2)}
# returns: 15
There you go, a perfect solution to the problem you stated. It is a wrapper, you don't need to pass in the arguments, and it should work for any function. If you need it to work with class objects or something you can read the docs for inspect
and see how to do it.
Note, of course order is not preserved in dictionaries, so you may not see the exact order I saw when I tested this. But the same values should be in the dict.
def foo(a, b, c):
args = {"a": a, "b": b, "c": c}
精彩评论