Get a list/tuple/dict of the arguments passed to a function?

45,178

Solution 1

You can use locals() to get a dict of the local variables in your function, like this:

def foo(a, b, c):
    print locals()

>>> foo(1, 2, 3)
{'a': 1, 'c': 3, 'b': 2}

This is a bit hackish, however, as locals() returns all variables in the local scope, not only the arguments passed to the function, so if you don't call it at the very top of the function the result might contain more information than you want:

def foo(a, b, c):
    x = 4
    y = 5
    print locals()

>>> foo(1, 2, 3)
{'y': 5, 'x': 4, 'c': 3, 'b': 2, 'a': 1}

I would rather construct a dict or list of the variables you need at the top of your function, as suggested in the other answers. It's more explicit and communicates the intent of your code in a more clear way, IMHO.

Solution 2

You can use the inspect module:

def foo(x):
    return x

inspect.getargspec(foo)
Out[23]: ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)

This is a duplicate of this and this.

Solution 3

Here's a function you can call to get the kwargs of the current function. Or if you want to use those lines directly in your own function instead of calling get_kwargs() just remove the .f_back

import inspect


def get_kwargs():
    frame = inspect.currentframe().f_back
    keys, _, _, values = inspect.getargvalues(frame)
    kwargs = {}
    for key in keys:
        if key != 'self':
            kwargs[key] = values[key]
    return kwargs


def test(x, y=100):
    z = 7
    print(get_kwargs())


test(5, 6)
# Output: {'x': 5, 'y': 6}
test(5)
# Output: {'x': 5, 'y': 100}

Solution 4

I would use *args or **kwargs and throw an exception if the arguments are not as expected

If you want to have the same errors than the ones checked by python you can do something like

def check_arguments(function_name,args,arg_names):
    missing_count = len(arg_names) - len(args)
    if missing_count > 0:
        if missing_count == 1:
            raise TypeError(function_name+"() missing 1 required positionnal argument: "+repr(arg_names[-1]))
        else:
            raise TypeError(function_name+"() missing "+str(missing_count)+" required positionnal argument: "+", ".join([repr(name) for name in arg_names][-missing_count:-1])+ " and "+repr(arg_names[-1]))

using with somethin like

def f(*args):
    check_arguments("f",args,["a","b","c"])
    #whatever you want
    ...

Solution 5

From the accepted answer from a duplicate (older??) question https://stackoverflow.com/a/582206/1136458 :

    frame = inspect.currentframe()
    args, _, _, values = inspect.getargvalues(frame)
Share:
45,178
user3047801
Author by

user3047801

Delivery-focussed Elixir/Erlang, Python, XSL/XQuery, and (No)SQL developer, specialising in content/data migration, API/micro-service design, and Scrum mentorship.

Updated on July 08, 2022

Comments

  • user3047801
    user3047801 almost 2 years

    Given the following function:

    def foo(a, b, c):
        pass
    

    How would one obtain a list/tuple/dict/etc of the arguments passed in, without having to build the structure myself?

    Specifically, I'm looking for Python's version of JavaScript's arguments keyword or PHP's func_get_args() method.

    What I'm not looking for is a solution using *args or **kwargs; I need to specify the argument names in the function definition (to ensure they're being passed in) but within the function I want to work with them in a list- or dict-style structure.