views:

2586

answers:

4

Given the python function:

def aMethod(arg1, arg2):
    pass

How can I extract the number and names of the arguments. Ie. given that I have a reference to func, I want the func.[something] to return ("arg1", "arg2")

The usage scenario for this is that I have a decorator, and I wish to use the method arguments in the same order that they appear for the actual function as a key. Ie. how would the decorator look that printed "a,b" when I call aMethod("a","b")

+14  A: 

In CPython, the number of arguments is

aMethod.func_code.co_argcount

and their names are in the beginning of

aMethod.func_code.co_varnames

These are implementation details of CPython, so this probably does not work in other implementations of Python, such as IronPython and Jython.

One portable way to admit "pass-through" arguments is to define your function with the signature func(*args, **kwargs). This is used a lot in e.g. matplotlib, where the outer API layer passes lots of keyword arguments to the lower-level API.

Jouni K. Seppänen
co_varnames does work with standard Python, but this method is not preferable since it will also display the internal arguments.
MattK
+28  A: 

Take a look at the inspect module - this will do the inspection of the various code object properties for you.

>>> inspect.getargspec(aMethod)
(['arg1', 'arg2'], None, None, None)

The other results are the name of the *args and **kwargs variables, and the defaults provided. ie.

>>> def foo(a,b,c=4, *arglist, **keywords): pass
>>> inspect.getargspec(foo)
(['a', 'b', 'c'], 'arglist', 'keywords', (4,))
Brian
+3  A: 

Here is something I think will work for what you want, using a decorator.

class LogWrappedFunction(object):
    def __init__(self, function):
        self.function = function

    def logAndCall(self, *arguments, **namedArguments):
        print "Calling %s with arguments %s and named arguments %s" %\
                      (self.function.func_name, arguments, namedArguments)
        self.function.__call__(*arguments, **namedArguments)

def logwrap(function):
    return LogWrappedFunction(function).logAndCall

@logwrap
def doSomething(spam, eggs, foo, bar):
    print "Doing something totally awesome with %s and %s." % (spam, eggs)


doSomething("beans","rice", foo="wiggity", bar="wack")

Run it, it will yield the following output:

C:\scripts>python decoratorExample.py
Calling doSomething with arguments ('beans', 'rice') and named arguments {'foo':
 'wiggity', 'bar': 'wack'}
Doing something totally awesome with beans and rice.
kevin holzer
A: 

I think what you're looking for is the locals method -


In [6]: def test(a, b):print locals()
   ...: 

In [7]: test(1,2)              
{'a': 1, 'b': 2}
Damian