383

Is there an easy way to be inside a python function and get a list of the parameter names?

For example:

def func(a,b,c):
    print magic_that_does_what_I_want()

>>> func()
['a','b','c']

Thanks

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
R S
  • 11,359
  • 10
  • 43
  • 50

4 Answers4

477

Well we don't actually need inspect here.

>>> func = lambda x, y: (x, y)
>>> 
>>> func.__code__.co_argcount
2
>>> func.__code__.co_varnames
('x', 'y')
>>>
>>> def func2(x,y=3):
...  print(func2.__code__.co_varnames)
...  pass # Other things
... 
>>> func2(3,3)
('x', 'y')
>>> 
>>> func2.__defaults__
(3,)

For Python 2.5 and older, use func_code instead of __code__, and func_defaults instead of __defaults__.

simplyharsh
  • 35,488
  • 12
  • 65
  • 73
293

locals() returns a dictionary with local names:

def func(a, b, c):
    print(locals().keys())

prints the list of parameters. If you use other local variables those will be included in this list. But you could make a copy at the beginning of your function.

Neuron
  • 5,141
  • 5
  • 38
  • 59
  • 3
    `print locals().keys()` will return `['arg']`. I used `print locals.get('arg')` – yurisich Nov 07 '12 at 22:32
  • 1
    @Droogans please check again. The solution from @unbeknown prints `['a', 'b', 'c']` (possibly not in a-b-c order), as expected. Your solution (a) doesn't work, raises an `AttributeError` -- maybe you meant `print locals().get('arg')`? and (b) if that's what you were trying to do, that prints the value of the parameter, not the name of the parameter as the OP requested. – Chris Johnson Sep 23 '13 at 10:00
  • 13
    Thank you! I have a new love for `"found {thing} in {place}, took {action}, resulting in {result}".format(**locals())` instead of `"found {thing} in {place}, took {action}, resulting in {result}".format(thing=thing, place=place, action=action, result=result)` – Bruno Bronosky Mar 26 '15 at 13:13
  • 7
    watch out, `locals()` returns namespace vars too, eg `def func(a,b,c): d=4; print(locals()['d'])` – Tcll Mar 30 '19 at 21:17
  • 5
    @BrunoBronosky why not just use f-strings? `f'found {thing} in {place}, took {action}, resulting in {result}'` – speedstyle Jul 20 '19 at 20:05
  • You can also identically replace `locals()` with `vars()`. – fantabolous Oct 03 '19 at 07:50
  • 2
    @speedstyle f-strings were introduced in Python 3.6. The comment was from 3.5. (And yes, f-strings are waay better :D ) – GeeTransit Dec 11 '19 at 21:25
  • "But you could make a copy at the beginning of your function." - This doesn't help , at least in 3.x; the names of local variables are determined at compile time, and `locals()` will contain them all. – Karl Knechtel Jan 14 '23 at 06:08
191

If you also want the values you can use the inspect module

import inspect

def func(a, b, c):
    frame = inspect.currentframe()
    args, _, _, values = inspect.getargvalues(frame)
    print 'function name "%s"' % inspect.getframeinfo(frame)[2]
    for i in args:
        print "    %s = %s" % (i, values[i])
    return [(i, values[i]) for i in args]

>>> func(1, 2, 3)
function name "func"
    a = 1
    b = 2
    c = 3
[('a', 1), ('b', 2), ('c', 3)]
kmkaplan
  • 18,655
  • 4
  • 51
  • 65
  • 14
    [Kelly Yancey's blog](http://kbyanc.blogspot.com/2007/07/python-aggregating-function-arguments.html) has a great post explaining this in detail and giving a slightly more refined version, plos a comparison with, e.g. unbeknown's solution. Recommended. – dan mackinlay Feb 04 '11 at 00:53
  • what about `def foo(first, second, third, *therest):`? – MeadowMuffins Apr 27 '17 at 11:27
  • 2
    how to use this functionality in a decorator? – JDOaktown Jan 15 '22 at 21:54
150
import inspect

def func(a,b,c=5):
    pass

>>> inspect.getargspec(func)  # inspect.signature(func) in Python 3
(['a', 'b', 'c'], None, None, (5,))

so for getting arguments list alone use:

>>> inspect.getargspec(func)[0]
['a', 'b', 'c']
mirekphd
  • 4,799
  • 3
  • 38
  • 59
Oli
  • 15,345
  • 8
  • 30
  • 36
  • 1
    That's not inside the function.. – R S Feb 24 '09 at 15:34
  • 15
    you can do it inside the function too – Oli Feb 25 '09 at 07:23
  • 12
    this is actually better, since it shows how to get at parameters of method you didn't write yourself. – Dannid Jun 02 '14 at 16:53
  • 1
    How can this be done _inside_ the function, though? – Unverified Contact Jun 20 '18 at 08:19
  • "defaults is a tuple of default argument values or None if there are no default arguments; if this tuple has n elements, they correspond to the last n elements listed in args." documentation – Mesco Jul 15 '18 at 11:16
  • 1
    @UnverifiedContact Just do it inside the function :-). You can access the function name with no problem (ie recursion) so `inspect.getargspec(func)` from within `func` should work just fine – Samie Bencherif Feb 14 '19 at 17:08
  • 6
    @DavidC Updated link [`inspect.signature`](https://docs.python.org/3/library/inspect.html#inspect.signature) – A T Oct 22 '20 at 09:30