Get a function argument's default value?
For this function
def eat_dog(name, should_digest=True):
print "ate dog named %s. Digested, too? %" % (name, str(should_digest))
I want to, external to the function, read its arguments and any default values attached. So for this specific example, I want to know that name
has no default value (i.e. that it is a required argument) and that True
is the default value for should_digest
.
I'm aware of inspect.getargspec()
, which does give me information about arguments and default values, but I see no connection between the two:
ArgSpec(args=['name', 'should_digest'], varargs=None, keywords=None, defaults=(True,))
From this output how can I tell that True
(in the defaults
tuple) is the default value for should_digest
?
Additionally, I'm aware of the "ask for forgiveness" model of approaching a problem, but unfortunately output from that error won't tell me the name of the missing argument:
>>> eat_dog()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: eat_dog() takes at least 1 argument (0 given)
To give context (why I want to do this), I'm exposing functions in a module over a JSON API. If the caller omits certain function arguments, I want to return a specific error that names the specific function argument that was omitted. If a client omits an argument, but there's a default provided in the function signature, I want to use that default.
Solution 1:
Python3.x
In a python3.x world, you should probably use a Signature
object:
import inspect
def get_default_args(func):
signature = inspect.signature(func)
return {
k: v.default
for k, v in signature.parameters.items()
if v.default is not inspect.Parameter.empty
}
Python2.x (old answer)
The args/defaults can be combined as:
import inspect
a = inspect.getargspec(eat_dog)
zip(a.args[-len(a.defaults):],a.defaults)
Here a.args[-len(a.defaults):]
are the arguments with defaults values and obviously a.defaults
are the corresponding default values.
You could even pass the output of zip
to the dict
constructor and create a mapping suitable for keyword unpacking.
looking at the docs, this solution will only work on python2.6 or newer since I assume that inspect.getargspec
returns a named tuple. Earlier versions returned a regular tuple, but it would be very easy to modify accordingly. Here's a version which works with older (and newer) versions:
import inspect
def get_default_args(func):
"""
returns a dictionary of arg_name:default_values for the input function
"""
args, varargs, keywords, defaults = inspect.getargspec(func)
return dict(zip(args[-len(defaults):], defaults))
Come to think of it:
return dict(zip(reversed(args), reversed(defaults)))
would also work and may be more intuitive to some people.
Solution 2:
You can use inspect
module with its getargspec
function:
inspect.getargspec(func)
Get the names and default values of a Python function’s arguments. A
tuple
of four things is returned:(args, varargs, keywords, defaults)
.args
is a list of the argument names (it may contain nested lists).varargs
andkeywords
are the names of the*
and**
arguments orNone
.defaults
is a tuple of default argument values orNone
if there are no default arguments; if this tuple hasn
elements, they correspond to the lastn
elements listed inargs
.
See mgilson's answer for exact code on how to retrieve argument names and their default values.