How to get method parameter names?
Solution 1
Take a look at the inspect
module - this will do the inspection of the various code object properties for you.
>>> inspect.getfullargspec(a_method)
(['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.getfullargspec(foo)
(['a', 'b', 'c'], 'arglist', 'keywords', (4,))
Note that some callables may not be introspectable in certain implementations of Python. For Example, in CPython, some built-in functions defined in C provide no metadata about their arguments. As a result, you will get a ValueError
if you use inspect.getfullargspec()
on a built-in function.
Since Python 3.3, you can use inspect.signature()
to see the call signature of a callable object:
>>> inspect.signature(foo)
<Signature (a, b, c=4, *arglist, **keywords)>
Solution 2
In CPython, the number of arguments is
a_method.func_code.co_argcount
and their names are in the beginning of
a_method.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.
Solution 3
The Python 3 version is:
def _get_args_dict(fn, args, kwargs):
args_names = fn.__code__.co_varnames[:fn.__code__.co_argcount]
return {**dict(zip(args_names, args)), **kwargs}
The method returns a dictionary containing both args and kwargs.
Solution 4
In a decorator method, you can list arguments of the original method in this way:
import inspect, itertools
def my_decorator():
def decorator(f):
def wrapper(*args, **kwargs):
# if you want arguments names as a list:
args_name = inspect.getargspec(f)[0]
print(args_name)
# if you want names and values as a dictionary:
args_dict = dict(itertools.izip(args_name, args))
print(args_dict)
# if you want values as a list:
args_values = args_dict.values()
print(args_values)
If the **kwargs
are important for you, then it will be a bit complicated:
def wrapper(*args, **kwargs):
args_name = list(OrderedDict.fromkeys(inspect.getargspec(f)[0] + kwargs.keys()))
args_dict = OrderedDict(list(itertools.izip(args_name, args)) + list(kwargs.iteritems()))
args_values = args_dict.values()
Example:
@my_decorator()
def my_function(x, y, z=3):
pass
my_function(1, y=2, z=3, w=0)
# prints:
# ['x', 'y', 'z', 'w']
# {'y': 2, 'x': 1, 'z': 3, 'w': 0}
# [1, 2, 3, 0]
Solution 5
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}
Related videos on Youtube
Comments
-
Staale over 2 years
Given the Python function:
def a_method(arg1, arg2): pass
How can I extract the number and names of the arguments. I.e., given that I have a reference to
func
, I want thefunc.[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. I.e., how would the decorator look that printed
"a,b"
when I calla_method("a", "b")
?-
Nick over 13 yearsFor a different list of answers to a nearly identical question, see this other stackoverflow post
-
Juh_ almost 12 yearsYour title is misleading: when one say 'method' w.r.t the word 'function', one usually think of a class method. For function, your selected answer (from Jouni K. Seppanen) is good. But for (class) method, it is not working and the inspect solution (from Brian) should be used.
-
-
MattK over 13 yearsco_varnames does work with standard Python, but this method is not preferable since it will also display the internal arguments.
-
hochl over 13 yearsWhy not use aMethod.func_code.co_varnames[:aMethod.func_code.co_argcount]?
-
Piotr Dobrogost over 12 yearsThis is useless outside of a function which is the context of interest here (decorator).
-
Andre Holzner over 11 yearssee also stackoverflow.com/a/3999574/288875 on examining callables in general
-
fatuhoku almost 11 yearsHow could the code possibly know that the default parameter
(4,)
corresponds to the keyword parameterc
specifically? -
Soverman over 10 years@fatuhoku I was wondering the same thing. Turns out it's not ambiguous since you can only add default arguments at the end in a contiguous block. From the docs: "if this tuple has n elements, they correspond to the last n elements listed in args"
-
javabeangrinder almost 9 yearsActually exactly what I was looking for although it is not the answer to the question here.
-
Diego Andrés Díaz Espinoza almost 8 yearsI think since Python 3.x getargspec(...) is replaced by inspector.signature(func)
-
Charlie Parker almost 8 yearsJust emphasize the fact that this doesn't work with built in since I recently discovered that if the function is in C it seems it won't work for some reason, see: stackoverflow.com/questions/39194325/….
-
theannouncer over 7 yearsChanged in version 2.6: Returns a named tuple ArgSpec(args, varargs, keywords, defaults).
-
Peter Majko almost 7 yearsdir() returns list of all variable names ['var1', 'var2'], vars() returns dictionary in form {'var1': 0, 'var2': 'something'} from within the current local scope. If someone wants to use argument variables names later in the function, they should save in another local variable, because calling it later in the function where they could declare another local variables will "contaminate" this list. In the case they want to use it outside of the function, they must run function at least once and save it in global variable. So it's better to use inspect module.
-
j08lue over 6 yearsThat is right, @DiegoAndrésDíazEspinoza - in Python 3,
inspect.getargspec
is deprecated, but the replacement isinspect.getfullargspec
. -
Hendrik Wiese almost 6 yearsIt's probably frowned upon here but as a German I cannot resist, sorry about that, but I somehow like the parameter name 'arglist'.
-
Blairg23 over 5 years
>>> inspect.getargspec(api_function)
./manage.py:1: DeprecationWarning: inspect.getargspec() is deprecated, use inspect.signature() or inspect.getfullargspec()
#!/usr/bin/env python3
-
Matthew D. Scholefield over 5 yearsYou can now do
inspect.signature(api_function).bind(*args).parameters
as mentioned in this answer: stackoverflow.com/a/45781963/2132312 -
Soren Bjornstad about 5 yearsNotice that the
[:fn.__code__.co_argcount]
is very important if you're looking for the function arguments -- otherwise it includes names created within the function as well. -
Nikolay Makhalin almost 5 yearsNot working with arguments after
*args
, e.g.:def foo(x, *args, y, **kwargs): # foo.__code__.co_argcount == 1
-
Kiann over 4 yearswhat if we would like to get the list of possible values for each argument? Is there a way?
-
Brian McCutchon over 4 years@Nikolay see stackoverflow.com/questions/147816/…
-
Brian McCutchon over 4 yearsPlease use inspect instead. Otherwise, your code doesn't work well with functools.wraps in 3.4+. See stackoverflow.com/questions/147816/…
-
Imago over 4 yearsThis answer is partially obsolete and should be updated.
-
Ciro Santilli OurBigBook.com almost 4 yearsOne problem with this is that it does not show if an argument is
*args
or**kwargs
. -
Dmytro Bugayev about 3 yearsneat solution. Would be even nicer if could be generalised for instance and class methods, for which the offset needs to start at 1 to skip over the self/cls arg
-
Michał Jabłoński over 2 yearsIf you only want a param list, then
list(inspect.signature(function).parameters)
is enough, you don't need to call the.keys()
method. Anyway, this is a great answer. -
Nicholas Jela over 2 yearsthis code even can not be run
-
Dust break about 2 yearswhich one is better?
fn.__code__.co_varnames[:fn.__code__.co_argcount]
orinspect.getargspec(f)[0]
-
Thingamabobs about 2 years
co_argcount
includes keywords, sof_code.co_kwonlyargcount
is not needed.