Getting list of parameter names inside python function [duplicate]
Asked Answered
B

4

395

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

Biddie answered 24/2, 2009 at 14:56 Comment(0)
R
489

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,)
Refit answered 29/10, 2010 at 11:40 Comment(11)
that'd be func.func_code.co_varnames[:func.func_code.co_argcount] since co_varnames is a tuple of all variables present in the functionIver
In python3 this would be func.__code__.co_varnamesImpending
This only works for non 'builtin_function_or_method'.Endways
@mikeschuldt Updated answer for Python3Viscera
I suppose it's better inspect for Python 2/3 compatibility.Googolplex
I use Python 2.7.8, and __code__ seems to be backported. func_code also still works.Revell
It will not work with function produced with functools.partial. For these you need to look at f.func and remove f.keyword and f.args.Octopus
@Revell - __code__ was introduced in Python 2.6, released in October 2008. 3.0 came out in December 2008. So I wouldn't say it was "backported" - 3.0 branched off of 2.6. The only version with features that were backported from 3 is 2.7.Mythological
code is 2.6-3.X compatible, so is fairly portableGusty
Please use inspect. Otherwise, your code doesn't work well with functools.wraps in 3.4+. See #148316Marcelenemarcelia
func.func_code.co_varnames[:func.func_code.co_argcount] excludes any keyword-only arguments, i.e. for a function defined as def f(a, b, *, c, d): this will only return ('a', 'b').Radioactivity
S
301

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.

Swathe answered 24/2, 2009 at 15:3 Comment(9)
print locals().keys() will return ['arg']. I used print locals.get('arg')Boon
@Droogans please check again. The solution from @Swathe 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.Anglophobe
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)Oscillator
watch out, locals() returns namespace vars too, eg def func(a,b,c): d=4; print(locals()['d'])Octavus
@BrunoBronosky why not just use f-strings? f'found {thing} in {place}, took {action}, resulting in {result}'Pegpega
You can also identically replace locals() with vars().Parabolize
@Pegpega f-strings were introduced in Python 3.6. The comment was from 3.5. (And yes, f-strings are waay better :D )Linwoodlinz
"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.Hager
@KarlKnechtel. I tried the solution in Python 3.11 and it works ok.: def func(a, b, c): args = locals(); d = 55; print(args); print(locals()) prints args only with a, b,c, but locals printed at the end includes d and also args. So, making a copy at the beginning seems to work.Twocolor
N
197

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)]
Nadbus answered 24/2, 2009 at 15:34 Comment(4)
Kelly Yancey's blog 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.Anesthetic
what about def foo(first, second, third, *therest):?Stirrup
how to use this functionality in a decorator?Bois
@Bois a decorator function/class takes a function/class as its argument. Therefore, given a python 3 decorator function def decorate(fn): ..., you would simply do fn_params = inspect.signature(fn).parameters in the decorator and use logic to get the argument values in fn's wrapper, def wrapper(*args, **kwargs): ..., which is returned by the decorator.Wendell
K
156
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']
Kiruna answered 24/2, 2009 at 15:31 Comment(7)
That's not inside the function..Biddie
you can do it inside the function tooKiruna
this is actually better, since it shows how to get at parameters of method you didn't write yourself.Photometer
How can this be done inside the function, though?Diorite
"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." documentationIndiscreet
@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 fineLubricity
@DavidC Updated link inspect.signatureMeldameldoh

© 2022 - 2024 — McMap. All rights reserved.