开发者

In python is there any way I can obtain the arguments passed to a function as object?

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}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜